パターンマッチ
引数の値による条件分岐が行える。オシャレ。上から条件に合った式が見つかれば、以降の式は評価されない。
lucky :: Int -> String lucky 7 = "lucky number seven!" lucky x = "out of lucky"
ghci> lucky 2 "out of lucky" ghci> lucky 7 "lucky number seven!"
複数の引数のパターンマッチ
list2split :: Int -> Int -> Int -> Int -> Int list2split x y 2 3 = x + y
ghci> list2split 2 7 2 3 9
パターンマッチによる再帰
再帰の終了条件となる式をパターンマッチを使用して記述できる。大変オシャレ。この辺りからHaskell楽しいと感じはじめた(^_^)
factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial(n -1)
ghci> factorial 5 120
タプルのパターンマッチ
マッチしたタプルの要素を束縛できる。
addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
ghci> :t addVectors addVectors :: (Double, Double) -> (Double, Double) -> (Double, Double) ghci> addVectors (4.0, 7.0) (2.0, 8.0) (6.0,15.0)
束縛する必要がない場合、_
で使用しないことを明言できる。
funcname :: (a, b, c) -> c funcname (_, _, z) = z
リスト内包表記のパターンマッチ
リスト内包表記もパターンマッチしたものを束縛できる。オシャレ。
ghci> [x | (x, 4) <- [ (1,4), (5,5), (7,4) ]] [1,7]
リストのパターンマッチ
リスト[1,2]
は1:[2]
の糖衣構文の為、コンスでパターンマッチでき、先頭と以降のリストを束縛できる。とてもオシャレ。コンスでパターンマッチする場合は()
でくくらないとsyntax errorになる。
list2split :: [a] -> (a,[a]) list2split [] = error "empty list" list2split (x:xs) = (x, xs)
ghci> list2split [1,2,3] (1,[2,3]) ghci> list2split [3] (3,[])
error関数はランタイムエラーを発生させる。
asパターン
束縛した変数とマッチ対象としたソースも同様に束縛する。
firstCharacterBy :: String -> String firstCharacterBy all@(x:_) = all ++ " first character is " ++ [x]
ghci> firstCharacterBy "Hello" "Hello first character is H"
パターンマッチに式を用いる
guardCase :: Int -> Int guardCase n | n == 0 = 1 | n < 10 = 10 | n < 100 = 100 | otherwise = 50
ghci> guardCase 0 1 ghci> guardCase 9 10 ghci> guardCase 99 100 ghci> guardCase 101 50
where パターンマッチの比較に用いる式を束縛する
パターンマッチの対象を式から計算する時、whereを用いて束縛することができる。
whereCase :: Int -> Int -> Int whereCase n m | ans == 0 = 0 | ans < 10 = 10 | otherwise = 11 where ans = n + m
ghci> whereCase 0 0 0 ghci> whereCase 0 1 10 ghci> whereCase 5 12 11
whereの中でもパターンマッチで束縛できる。
whereCase :: Int -> Int -> Int whereCase n m | x == ans = 0 | ans < 10 = 10 | otherwise = x where ans = n + m (x:_) = [1,2]
whereは関数を返すこともできるので、where内で、関数パターンマッチを記述することもできる。
whereCase :: [Int] -> Int whereCase xs | funcName xs == 0 = 1 | otherwise = funcName xs where funcName [] = 0 funcName (x:_) = x
ghci> whereCase [] 1 ghci> whereCase [3,2,1] 3
任意のタイミングで値を束縛する let式
let
で束縛し、in
に式を記述する。また値に限らず関数などもletに束縛できる。
letExp :: Int -> Int -> Int letExp n m = let ans = n * m in ans
関数の束縛
ghci> [let sample x = x * x in (sample 2, sample 4, sample 5)] [(4,16,25)]
またセミコロンで区切ることで複数の変数に対して束縛できる。
let a = 1; b = 2 in a * 2
リスト内包表記でのlet
inで式を書かず、述語として束縛のみ行える。
ghci> [ans| x <- [1,2,3], let ans= x * 2] [2,4,6]
case式
関数パターンマッチの糖衣構文。
caseFunc :: [Int] -> Int caseFunc xs = case xs of [] -> 1 (x:_) -> x
ghci> caseFunc [] 1 ghci> caseFunc [3] 3
リンク
リンク