すごいHaskellを読み続ける毎日。
身長と体重の数字を与えると、BMIをご丁寧に計算した上、お前は骨皮だのデブだのと罵倒する、いかにもHaskell(イメージ)なサンプルプログラムが掲載されていたので書いてみます。
bmiTell :: Double -> Double -> String
bmiTell weight height
| bmi <= 18.5 = show bmi ++ " yase"
| bmi <= 25.0 = show bmi ++ " hutu-"
| bmi <= 30.0 = show bmi ++ " debu"
| otherwise = show bmi ++ " very debu"
where bmi = weight / height ^ 2
返されるコメント部分は、ホントはもっと長い。長いコメント返すのが目的じゃないのでdebuとかにしました。
あたしは今のとこBMI23くらいなので(痩せました!)、あんま酷い罵倒はされません。よかったです。
で、この書き方がパターンマッチングと双璧をなす、かどうかはわからないが、関数の定義の際に便利な書き方であるということを覚えました。
switch文みたいだ。
個人的には、where以下で定義できる、変数やら関数やらの周辺に違和感を感じます。なんで後ろに並べるのか。手前の数行で使われる変数について知りたいときに、末尾を目で追わないといけないというのは不便な気がするんだけどなあ。
なんとなく、動作の内容が重要なのであって、値は二の次なんだよという姿勢の一環なのかなという感触。
文句はともかく、こういうのは繰り返し書き取りすることでしか身につかないので、手元で色々くだらないアレコレを書くことにします。
ohoho :: (Num a, Num a1) => a -> a1 -> [Char]
ohoho x y
| x == 1 && y == 1 = "1 1"
| x == 1 && y /= 1 = "1 ?"
| x /= 1 && y == 1 = "? 1"
| otherwise = "Boo"
意味も中身もマトモにないけど書き取りの練習だからコレ。
で、ふと思う。
こういう、True and TrueはTrueでTrue or FalseはFalseですみたいなのはどう書いてるんだ実際。演算子あんのか。
*Main> 1 & 1
:1:3: Not in scope: `&'
*Main> 1 `&` 1
:1:4: parse error on input `&'
*Main> (&) 1 0
:1:1: Not in scope: `&'
ない。困りますそういうのは。
いやあるだろ。ないといろいろ無理だろう。探します。
「haskell 演算子」でぐぐりますと見つかったページが神がかっており、そこの一覧を眺めますと、ありました。
Haskellの演算子について纏めてみた@開発やプログラミングや家族や思考
すごい。
Bool
&じゃなくて&&だった。
Bool (&&) 論理積
Bool (||) 論理和
とあるので、さっそくやってみる。
*Main> (&&) 1 0
:1:8:
No instance for (Num Bool)
arising from the literal `0'
Possible fix: add an instance declaration for (Num Bool)
In the second argument of `(&&)', namely `0'
In the expression: (&&) 1 0
In an equation for `it': it = (&&) 1 0
おい。んー、表に「Bool」ってある。
あー。
*Main> (&&) True False
False
真偽値じゃないもん放り込んでんじゃねえよデブって言われてたんですね。デブじゃないし。BMI23だし。
Bits
当該ページの下の方に、似たようなのがあります。
Bits (.&.) ビットAND
Bits (.|.) ビットOR
びっと。ためしにやってみる。
Prelude> (.&.) 1 0
:1:1: Not in scope: `.&.'
Prelude> (.&.) True False
:1:1: Not in scope: `.&.'
そもそもスコープにないって。そんな関数知らねえよってこと?え?
あたしはそのへんピンときちゃう。
*Main> import Bits
*Main Bits>
今日は天気が悪い(あたしにとってはいい天気)なのでザジテン飲んでないんだ。頭冴えてます。
*Main Bits> (.&.) True False
:1:1:
No instance for (Bits Bool)
arising from a use of `.&.'
Possible fix: add an instance declaration for (Bits Bool)
In the expression: (.&.) True False
In an equation for `it': it = (.&.) True False
*Main Bits> (.&.) 1 0
0
こっちは、真偽値じゃなくて01を受け取るのか。
冴えてもこの程度ですがあたしは生きています。
さらにピン
*Main> 1 `and` 1
:1:1:
The operator `and' takes two arguments,
but its type `[Bool] -> Bool' has only one
In the expression: 1 `and` 1
In an equation for `it': it = 1 `and` 1
だめか。だめとおもいきや、ちょっとエラーメッセージがちがう。
なんだ?
*Main> and True False
*Main> True and False
*Main> 1 and 1
*Main> 1 and 0
*Main> 1 `and` 0
*Main> [1] `and` [0]
*Main> [True] `and` [False]
などと盲滅法に打ちまくり怒られまくったあとで、ようやっと
「but its type `[Bool] -> Bool' has only one」
とあるのに気づきます。なんでリストなのん……?
*Main> and [False]
False
*Main> and [True]
True
意味がわからない。役に立つのかコレ。
さらにピン。
*Main> and [True, False]
False
*Main> and [True, True]
True
こうだな。
*Main> and [True, True, False]
False
*Main> and [ 1, 1, 0]
:1:13:
No instance for (Num Bool)
arising from the literal `0'
Possible fix: add an instance declaration for (Num Bool)
In the expression: 0
In the first argument of `and', namely `[1, 1, 0]'
In the expression: and [1, 1, 0]
意図がわかった。なるほどー。なるほどねー。