Haskell IOアクション入出力の学習

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

IOアクション

IOアクションは実行されると副作用を含む動作を行い結果を返す。結果に返すべきものがない場合、()空のタプル、Unitを返す。

ghci> :t putStrLn 
putStrLn :: String -> IO ()
ghci> :t putStrLn "Hello World"
putStrLn "Hello World" :: IO ()

のように、putStrLnは文字列を受け取り、副作用を伴う動作を行いUnitを返す。という定義と読める。

IOアクションはmainという名前をつけてプログラムを起動すると実行される。

main = putStrLn "hello, world"


IOアクションをまとめる

IOアクションまとめてをmainに名前付けするにはdo構文を使用する。

main = do
  putStrLn "What's your name?"
  name <- getLine
  putStrLn $ "Hey" ++ name ++ ", you rock!"


getLine

getLineは副作用がある動作を行いStringを返す。上の例では<-で返されたStringをnameに束縛している。

ghci> :t getLine
getLine :: IO String

IOアクションは副作用のある世界に出向き、何かを持って帰ってくる箱と表現されている。

IOアクションそのものを引数にとるのではなく、IOアクションから値を取り出し引数に与えることで、値を引数にとる関数は副作用のない純粋性を保てる。


IOアクションとlet

<-IOアクションから返された結果を束縛、letは純粋な式の結果を束縛する。

import Data.Char
main = do
  putStrLn "What's your first name?"
  firstName <- getLine
  putStrLn "What's your last name?"
  lastName <- getLine
  let
    bigFirstName = map toUpper firstName
    bigLastName = map toUpper lastName
  putStrLn $ "Hey"
    ++ bigFirstName ++ " "
    ++ bigLastName
    ++ ", how are you?"
return

HaskellのreturnはIOアクションを返す。以下の例ではgetLineで入力せずEnterキーを押した場合、mainにIO ()が返されプログラムが終了する。

main = do
  line <- getLine
  if null line
    then return ()
    else do
      putStrLn $ reverseWords line
      main

reverseWords :: String -> String
reverseWords = unwords . map reverse . words

つまり以下で、returnが返すIOアクションの結果を束縛するという記述になる。

main = do
  name <- return "Mike"


when関数

when関数はif then elseのelseを省略したような動作を行う。1つ目の引数がTrueの時、2つ目の引数に渡されたIOアクションを返す。

import Control.Monad

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


sequence関数

sequence関数はIOアクションのリストを受け取り順に実行するIOアクションを返す。

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


mapM mapM_ 関数

mapM関数はIOアクションを返す関数を引数にとり、シーケンスを返す。mapM_ はIOアクションの結果を捨てる。

mapM_ print [1,2,3]


forever関数

forever関数はIOアクションを受け取りそのIOアクションを永遠に繰り返す。

import Control.Monad
import Data.Char

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


forM関数

forMはmapMの引数順序が逆のパターン。メソッド記述が末尾にくることにより、IOアクションを返すメソッドをラムダで記述することができる。

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 color