HOME |
2. プログラムを動かす |
Haskell のお勉強 |
4. 型 |
書き込む |
foo x y = x + y hoge = 2foo は2つの引数を取って、それらの和を返す関数です。一方、 hoge は引数を取らず、常に 2 を返す定数関数です。 これらをファイル(例えば a.hs)に書いたのちロードすると次のようになります。
Prelude> :l a.hs Main> foo 1 2 3 Main> hoge 2ちなみにプロンプトには hugs が最後に読み込んだモジュール名が表示されます。 hugs が立ち上がるとき Prelude というモジュールが読み込まれるので表示が Prelude になっています。一方、a.hs を読み込むと Main になるのは、 モジュール名を省略すると Main とみなされるからです。
01: -- pattern matching 02: factA 0 = 1 03: factA n = n * factA (n-1) 04: 05: -- guard 06: factB n | n==0 = 1 07: | otherwise = n * factB (n-1) 08: 09: -- if 10: factC n = if n==0 11: then 1 12: else n * factC (n-1) 13: 14: -- case of 15: factD n = case n of 16: 0 -> 1 17: _ -> n * factD (n-1)
bar _ = "I don't care arguments."
Main> bar "Do you mind arguments?" "I don't care arguments."
function_name arguments | predicate_1 = body_1 | predicate_2 = body_2 .................... | otherwise = body_otherwise例:
01: greeting is_woman age | is_woman && age < 20 = "I have never seen such a beautiful girl like you!" 02: | is_woman = "Nice to meet you." 03: | otherwise = "Sorry, I am busy now."
Main> greeting True 17 "I have never seen such a beautiful girl like you!" Main> greeting True 28 "Nice to meet you." Main> greeting False 21 "Sorry, I am busy now."guard も特定性の高いものから書きます。 上の例で1行目の guard と2行目を入れ替えると age はどうでもよくなります。 また、otherwise は残り全てにマッチします。
check n = if n > 0
then "OK"
else "Error"
score c = case c of
'a' -> 90
'b' -> 70
'c' -> 50
'd' -> 30
_ -> 0
_ は列記されている値以外の全てにマッチします。
例として、砲丸投げで、砲丸の飛ぶ距離を求める関数を書いてみました。 飛ぶ距離は初速度(m s-1) と地面との角度(度)の関数です。
shot_putting1 v0 angle = vx * t
where r = angle * pi / 180.0
vx = v0 * cos r
vy = v0 * sin r
t = 2 * vy / 9.8
where と guard
が併用されている場合、全ての guard が where
の定義を参照できます。
shot_putting2 v0 angle = let r = angle * pi / 180.0
vx = v0 * cos r
vy = v0 * sin r
t = 2 * vy / 9.8
in vx * t
dev_mod i j = iter i 0
where iter mod dev | mod < j = (dev, mod)
| otherwise = iter (mod - j) (dev + 1)
上の例では、単純に割られる数から割る数を引き、何回引けたかを数えます。
最後に引けなくなったときの、引けた回数が商で、残りが余りです。
引き算の回数を記録するために、記録用の引数を持った内部関数 iter を使っています。
iter の内部では、割る数 j が定義されていないので、
外側のクロージャーの j が使われます。
\argvs -> body -- for example \ x y -> x + y
x + y ⇔ (+) x y max a b ⇔ a `max` b
foo $ hoge x y ⇔ foo (hoge x y)
foo $ hoge x ⇔ (foo . hoge) x
shot_putting3 v0 angle = let{ r = angle * pi / 180.0;
vx = v0 * cos r;
vy = v0 * sin r;
t = 2 * vy / 9.8;
} in vx * t
明示的に表記すると処理系はインデントを無視します。
また、明示的な表記と、インデントによる表記を共存させることができます。
最後に主な(初心者向け) Tutorial へのリンクを張っておきます。
HOME |
2. プログラムを動かす |
Haskell のお勉強 |
4. 型 |
書き込む |