fugafuga.write

日々のログ



すごいH本 part59

I/O 関数

putStr

main = do
    putStr "Hey, "
    putStr "I'm "
    putStr "Andy!"

実行結果

*Main> main
Hey, I'm Andy!*Main>

文字列を引数として受け取る。 受け取った文字列を端末に表示するI/Oアクションを返す。 改行しない。

putChar

main = do
    putChar 't'
    putChar 'e'
    putChar 's'

実行結果

*Main> main
tes*Main>

文字を受け取り、それを端末に表示するI/Oアクションを返す。

print

main = do
    print True
    print 2
    print "haha"
    print 3.2
    print [3,4,3]

実行結果

*Main> main
True
2
"haha"
3.2
[3,4,3]

Show インスタンスの型の値を受け取り、 それに show を適用し、文字列化したものを端末に出力する。

putStrLn . show と同じ。

文字列を表示したい時は、putStrLn がよく使われるが、 他の型の値を表示するときは print が使われる。

when

import Control.Monad

main = do
    input <- getLine
        when (input == "SWORDFISH") $ do
                putStrLn input

実行結果

*Main> main
hoge
*Main> main
SWORDFISH
SWORDFISH

Bool と I/O アクションを受け取り、 Bool の値がTrueの場合には渡されたI/Oと同じものを返す。

do ブロックでは制御構文のように見えるが、普通の関数。 条件が満たされた場合に何らかのI/Oアクションをしたい場合に使う。

sequence

main = do
    rs <- sequence [getLine, getLine, getLine]
    print rs

実行結果

*Main> main
one
two
three
["one","two","three"]

I/O アクションのリストを受け取り、 それらを順に実行するI/Oアクション(シーケンス)を返す。

リストに対して print や putStrLn を map するときに使われる。

*Main> sequence $ map print [1,2,3,4]
1
2
3
4
[(),(),(),()]

最後の[(),(),(),()]は、

*Main> :t print
print :: Show a => a -> IO ()

で、print が返した結果のリスト。

mapM

リストに対してI/Oアクションをマップし、それをシーケンスにする。 という操作が頻出するため、ユーティリティ関数として用意されている。

*Main> mapM print [1,2,3]
1
2
3
[(),(),()]
*Main> mapM_ print [1,2,3]
1
2
3

I/O アクションの結果が不要な場合は、mapM_を使う。

forever

I/O アクションを受け取って、 受け取ったI/Oアクションを永遠に繰り返すI/Oアクションを返す。

import Control.Monad
import Data.Char

main = forever $ do
    putStr "Give me some input: "
    l <- getLine
    putStrLn $ map toUpper l

実行結果

*Main> main
Give me some input: hoge
HOGE
Give me some input: foo
FOO
Give me some input: piyoooo
PIYOOOO
Give me some input:

forM

mapM の引数が逆になったもの。リストとI/Oアクションをとり、 I/Oアクションのリストを返す。

import Control.Monad

main = do
    colors <- forM [1,2,3,4] $ \a -> do
        putStrLn $ "Which color do you associate with the number "
                   ++ show a ++ "?"
        color <- getLine
        return color
    putStrLn "The colors that you associate with 1, 2, 3 and 4 are: "
    mapM putStrLn colors

実行結果

*Main> main
Which color do you associate with the number 1?
Red
Which color do you associate with the number 2?
Blue
Which color do you associate with the number 3?
Yellow
Which color do you associate with the number 4?
Orange
The colors that you associate with 1, 2, 3 and 4 are:
Red
Blue
Yellow
Orange
[(),(),(),()]

mapMforMは関数とリストのどちらを長く書きたいかによって使い分けるのが吉らしい。

コンクルージョン

  • I/O アクションは値
  • main 関数の中に入っていると実行される

所感

[(),(),(),()]が全く意味解らなくて結構悩んだ。 画面に表示することと、 返されるI/Oアクションの結果が別ものだということに気づけなかった。

あと、I/O"アクション"なのに値というイメージが慣れない(名前的な問題)。 今のところは"端末に表示せよ"という命令が表現された値。 という感じで認識している。

7章の型の話の時も思ったが、 実際のプログラムと抽象化された情報操作のイメージの紐付けは練習するしかないっぽい。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る