Haskell 入門


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