by shigemk2

当面は技術的なことしか書かない

ガード

関数を定義する際、引数の構造で場合分けするときにはパターンを使う。
引数の値が満たす性質で場合分けするときはガードを使う。

パターンのときもそうだったが、
これを使いこなせないとif/then/elseを多用することになって可読性が著しく下がる。


ガードの例

式を評価して、Falseなら下へ続く。どれでもないならOtherwise

bmiTell :: Double -> String
bmiTell bmi
  | bmi <= 18.5 = "You're underweight"
  | bmi <= 25.0 = "You're normal"
  | bmi <= 30.0 = "You're fat"
  | otherwise = "You're a whale"

結果

Main> bmiTell 24
"You're normal"
Main> bmiTell 1
"You're underweight"
Main> bmiTell 28
"You're fat"
Main> bmiTell 100.55555
"You're a whale"

なお、全ての式を評価してFalseとなり、なおかつOtherwiseもFalseとなるなら、
「適切なパターンが見つからない」というエラーが返ってくる。

なお、ガードは複数の引数を取る関数にも使える。

bmiTell' :: Double -> Double -> String
bmiTell' weight height
  | weight / height ^ 2 <= 18.5 = "You're underweight"
  | weight / height ^ 2  <= 25.0 = "You're normal"
  | weight / height ^ 2  <= 30.0 = "You're fat"
  | otherwise = "You're a whale"

max' :: (Ord a) => a -> a -> a
max' a b
  | a <= b = b
  | otherwise = a

myCompare :: (Ord a) => a -> a -> Ordering
a `myCompare` b
  | a == b = EQ
  | a <= b = LT
  | otherwise = GT

結果

Main> bmiTell' 85 1.90
"You're normal"
Main> max' 4 300
300
Main> myCompare 4 4
EQ
Main> 3 `myCompare` 2
GT