fugafuga.write

日々のログ



すごいH本 part10

パート10までやってきた自分えらい

ガード

  • 引数の構造で場合分け
    • パターンマッチを使う
  • 引数の値が満たす性質で場合分け
    • ガードを使う

bmiTell :: Double -> String
bmiTell bmi
  | bmi <= 18.5 = "You're underweight, you emo, you!"
  | bmi <= 25.0 = "You're supposedly normal. Pfffft, I bet you're ugly!"
  | bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
  | otherwise   = "You're a whale, congratulations!"

実行

*Main> bmiTell 24.3
"You're supposedly normal. Pfffft, I bet you're ugly!"
*Main> bmiTell 1
"You're underweight, you emo, you!"
*Main> bmiTell 100
"You're a whale, congratulations!"
  • | <真偽値式> = <関数本体> *if/else使うよりガード使えとのこと
  • otherwiseでその他のパターンを拾う

その他の例

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> max' 1 3
3
*Main> 1 `myCompare` 3
LT

where

  • 計算の途中結果に名前を付けることができる
  • ガードの後に書く
bmiTell' :: Double -> Double -> String
bmiTell' weight height
  | bmi <= 18.5 = "You're underweight, you emo, you!"
  | bmi <= 25.0 = "You're supposedly normal. Pfffft, I bet you're ugly!"
  | bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
  | otherwise   = "You're a whale, congratulations!"
  where bmi = weight / height ^ 2

もうちょっと修正

bmiTell' :: Double -> Double -> String
bmiTell' weight height
  | bmi <= skinny = "You're underweight, you emo, you!"
  | bmi <= normal = "You're supposedly normal. Pfffft, I bet you're ugly!"
  | bmi <= fat    = "You're fat! Lose some weight, fatty!"
  | otherwise     = "You're a whale, congratulations!"
  where bmi = weight / height ^ 2
        skinny = 18.5
        normal = 25.0
        fat = 30.0

where ブロック内のインデントは揃えないと正しく動かない

where のスコープ

動かない例

greet :: String -> String
greet "Juan" = niceGreeting ++ " Juan!"
greet "Fernando" = niceGreeting ++ " Fernando!"
greet name = badGreeting ++ " " ++ name
  where niceGreeting = "Hello! So very nice to see you,"
        badGreeting = "Oh! Pffft. It's you."

この書き方だと、where で束縛された変数は最後の関数の本体からしか見えない。 greet name = ... の部分。そしてコンパイル時に怒られる。

*Main> :l src/chapter3.hs
[1 of 1] Compiling Main             ( src/chapter3.hs, interpreted )

src/chapter3.hs:56:16: error:
    Variable not in scope: niceGreeting :: [Char]

src/chapter3.hs:57:20: error:
    Variable not in scope: niceGreeting :: [Char]
Failed, modules loaded: none.

動く例

badGreeting :: String
badGreeting = "Oh! Pffft. It's you."

niceGreeting :: String
niceGreeting = "Hello! So very nice to see you,"

greet :: String -> String
greet "Juan" = niceGreeting ++ " Juan!"
greet "Fernando" = niceGreeting ++ " Fernando!"
greet name = badGreeting ++ " " ++ name

こんな感じで関数の外で定義してあげないと参照できない

*Main> greet "Juan"
"Hello! So very nice to see you, Juan!"
*Main> greet "tokoyax"
"Oh! Pffft. It's you. tokoyax"

where の中でパターンマッチ

initials :: String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
  where (f:_) = firstname
        (l:_) = lastname

where の中で関数定義

calcBmis :: [(Double), (Double)] -> [Double]
calcBmis xs = [bmi w h | (w, h) <- xs]
  where bmi weight height = weight / height ^ 2

今日はここまで

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る