標準入力から1行読んで標準入力に書く
-- do 表記法(モナドを使いやすくする表記法)を使う場合
main :: IO ()
main = do x <- getLine
putStrLn x -- putStrLnは文字列出力関数
-- 上記は以下の糖衣構文(理解できればこのケースではこちらがシンプル)
main :: IO ()
main = getLine >>= putStrLn
上記を(標準入力からの入力が終了する=EOF まで)繰り返す。
import System.IO
rl :: IO ()
rl=do
e<-isEOF
if e
then return ()
else do
r<-getLine
putStrLn r
rl
main :: IO ()
main=rl
rl を再帰的に呼ぶことで繰り返しを実現している。
isEOF関数で終了判定をしている。isEOFは System.IOモジュールに収められているのでそれを事前にimportしておく必要がある。
-- 同じプログラムの、doを使わない書き方
import System.IO
-- rl :: IO ()
rl = isEOF >>= (\e -> if e then return () else getLine>>=putStrLn>>=return rl)
-- main :: IO ()
main=rl
シンプルな繰り返し
mapM print [1..10]
基本的解説:
Show a => a
である型なら何でも受け取る。少し進んだ解説:
同じものを繰り返す
take 10 $ repeat "hello"
--- または
replicate 10 "hello"
これらの関数のシグニチャは以下のように確認しておくこと。
:t take --> take :: Int -> [a] -> [a]
:t repeat --> repeat :: a -> [a]
:t replicate --> replicate :: Int -> a -> [a]
同じものを一定回数繰り返してputStrLnさせるには、
-- リストからのアプローチ
mapM print $ replicate 10 "hello"
--or
sequence $ map print $ replicate 10 "hello"
-- 再帰関数を使う 書き方1 (if と >> を使う)
p :: Int -> [Char] -> IO ()
p n str=if n <=0 ‐‐ if 式で改行をどう入れるべきかは諸説ある
then return ()
else
print str >> p (n - 1) str
-- 書き方2 (ガード と do を使う) -- 以下型シグニチャは省略
p n str
|n<=0 = return ()
|otherwise = do
print str
p (n - 1) str
-- 書き方3 (場合分けした関数定義(パターンマッチが行われる))
p 0 str = return ()
p n str = print str >> p (n - 1) str
無名再帰の例
import Control.Monad.Fix
fix (\p n str -> if n <= 0 then return 0 else print str >> p (n-1) str) 10 "hello"