Haskell の制御構造
プログラム言語で分岐や繰り返しのないものはない。Haskell も例外ではない。以下にカタログ的に分岐や繰り返しのパターンを並べてみた。
分岐
if 文 (else 以下は省略できない)
Prelude> let absolute x = if x >= 0 then x else (-x) Prelude> absolute (-2) 2
case 文
Prelude> :set +m Prelude> let Prelude| choices x = Prelude| case x of Prelude| 1 -> "first" Prelude| 2 -> "second" Prelude| _ -> "other" Prelude| Prelude> choices 2 "second" Prelude> choices 5 "other"
ガード
Prelude> let Prelude| which n Prelude| | n == 0 = "zero" Prelude| | even n = "even" Prelude| | otherwise = "odd" Prelude| Prelude> which 2 "even" Prelude> which 5 "odd"
パターン
Prelude> let Prelude| toNum "one" = 1 Prelude| toNum "two" = 2 Prelude| toNum _ = 0 Prelude| Prelude> toNum "one" 1 Prelude> let Prelude| foo ('a':'b':_) = "ab" Prelude| foo ('c':'d':_) = "cd" Prelude| foo _ = "other" Prelude| Prelude> foo "bcdef" "other" Prelude> foo "cdef" "cd"
ガードとパターンの組み合わせ
Prelude> :m +Data.Char Prelude Data.Char> let Prelude Data.Char| what [] = "empty string!" Prelude Data.Char| what (c:_) Prelude Data.Char| | isUpper c = "upper case!" Prelude Data.Char| | isLower c = "lower case" Prelude Data.Char| | otherwise = "not a letter!" Prelude Data.Char| Prelude Data.Char> what "hello" "lower case"
2. くりかえし
再帰
Prelude> let Prelude| fact 0 = 1 Prelude| fact n = n * fact (n-1) Prelude| Prelude> fact 5 120
末尾再帰
Prelude> let Prelude| foo (i, sum) = Prelude| if i > 10 Prelude| then return sum Prelude| else foo (i+1, sum + i) Prelude| Prelude> foo (1,0) 55
リストの再帰
Prelude> let Prelude| foo [] = [] Prelude| foo (x:xs) = x * x : foo xs Prelude| Prelude> foo [1,2,3,4,5] [1,4,9,16,25]
IOモナドの再帰
Prelude> let Prelude| foo = do Prelude| cs <- getLine Prelude| if cs == "" Prelude| then return [] Prelude| else do Prelude| xs <- foo Prelude| return (cs:xs) Prelude| Prelude> foo hello world
畳み込み
Prelude> foldr (+) 0 [1,2,3,4,5] 15
map
Prelude> map (*2) [1,2,3,4,5] [2,4,6,8,10]
mapM_
Prelude> mapM_ putStrLn ["hello", "world"] hello world