![]() |
![]() |
![]() |
![]() |
![]() |
しかし、このことによって、副作用のある部分を副作用の無い関数から 隔離することが出来ます。
do 記法の代わりに >>= を使うことも出来ます。 この方法は Monad のところで説明します。 do ブロックは通常の関数と異なるのでアクションと呼ばれます。 do ブロックから外部に値を返すには return を用います。 return a とすると外部には IO a が返ります。 (正確な説明は Monad のところでします。)
ファイル読み込みなどの入力アクションが返す値は IO a と呼ばれ、 普通の a と区別されます。 IO a を a に換えるには、do ブロックの中で <- を使います。 <- の厳密な定義は モナドのところで説明します。
-- simple echo -- wrong, an IO String is not a String putStrLn $ getLine -- ok do str <- getLine -- converting IO String into String and 'bind' it to str putStrLn str -- also ok getLine >>= putStrLn以下に user account と password を聞き、正しければ log in したと表示する アクション login を示します。
login = do putStr "Enter user name: " user <- getLine putStr "Enter password: " pass <- getLine if is_user user pass then putStrLn $ user ++ " has logged in" else putStrLn "Permission denied." where is_user "Taro" "baseball" = True is_user "Hanako" "swimming" = True is_user _ _ = False
アクション名 | 型 | 説明 |
---|---|---|
writeFile | FilePath -> String -> IO () | FilePath に String を書きます。 |
appendFile | FilePath -> String -> IO () | FilePath に String を追加します。 |
readFile | FilePath -> IO String | FilePath から IO String を読みます。 |
例:file copy
copy_file from to = do contents <- readFile from writeFile to contents
module IO で定義されているアクションは
openFile, hClose, hFileSize, hIsEOF, isEOF, hSetBuffering, hGetBuffering, hFlush, hGetPosn, hSetPosn, hSeek, hWaitForInput, hReady, hGetChar, hGetLine, hLookAhead, hGetContents, hPutChar, hPutStr, hPutStrLn, hPrint, hIsOpen, hIsClosed, hIsReadable, hIsWritable, hIsSeekable, isAlreadyExistsError, isDoesNotExistError, isAlreadyInUseError, isFullError, isEOFError, isIllegalOperation, isPermissionError, isUserError, ioeGetErrorString, ioeGetHandle, ioeGetFileName, try, bracket, bracketなどがあります。 詳しくは The Haskell 98 Report, 21 Input/Output を見てください。
例:ファイルの最初の n 行を表示する。(UNIX コマンドの head に相当)
はじめの n 行を表示させたいときは、ファイルの内容全てを読むことは
無駄なので、n 行だけ読むようにします。
01: import IO 02: 03: fhead n filename = bracket (openFile filename ReadMode) 04: hClose 05: (\h -> do hSetBuffering h LineBuffering 06: take_line 0 h) 07: where take_line i h' | i == n = return () 08: | otherwise = do str <- hGetLine h' 09: putStrLn str 10: take_line (i+1) h'
説明:
行 | 説明 |
---|---|
01 | module IO を import します。 |
03 | 表示する行数とファイル名を引数として取るアクション fhead を定義します。 |
03-06 | bracket は 3 つの引数を取ります。
|
05 | IO buffer のサイズを LineBuffering にします。 |
06 | take_line はファイルハンドルから n 行読むアクションです。(7行目で定義) |
07--10 | take_line の定義です。 |
07 | n 行読み込んだら IO () を返します。 |
08 | そうでなければ、ファイルハンドルから 1 行読み込んで、 |
09 | 標準出力に吐き出して、 |
10 | 次の行を読み込んで表示します。(take_line を再帰) |
01: -- av.hs 02: -- just show command line arguments 03: module Main where 04: import System 05: 06: main = do putStrLn "The arguments are:" 07: av <- getArgs 08: putStr $ unlines av
D:\doc\05-03\haskell>runhugs av.hs hi how are you ? The arguments are: hi how are you ?
![]() |
![]() |
![]() |
![]() |
![]() |