![]() |
![]() |
![]() |
![]() |
![]() |
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.8where と 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 へのリンクを張っておきます。
![]() |
![]() |
![]() |
![]() |
![]() |