8. 例
isModBy4 = (id &&& flip mod 4) >>> first (repeat . Right)
>>> first ((:) $ Left True) >>> uncurry (!!)
8
•Intから(Int,Int)への関数。
•idは恒等関数といい、何もしない。id(x) = x
•flipは引数を逆転する関数。flip f x y = f y x
•modは割った余りを求める関数。mod x y = xをyで割った余り
•従って(flip mod 4) xはxを4で割った余りを求める関数。
※Haskellではカッコが多くなるのを防ぐために、
f(x)を f x と書いたり、
g(f(x))を g $ f x や g . f $ x と書いたりします。
(id &&& flip mod 4)1999 (1999, 3)
9. 例
isModBy4 = (id &&& flip mod 4) >>> first (repeat . Right)
>>> first ((:) $ Left True) >>> uncurry (!!)
9
•(Int, Int)から(Int, Either ??? Int)への関数。
•Either A Bは「型Aまたは型Bになる」という型。C言語のunionみたいな感じ。
•???の部分は先を読まないと分からない。
•Right xは、型Bの変数xを(Either ??? B)型に変換する関数。
•repeat xはxを要素として持つ無限リスト[x, x, x, ・・・]を作る関数。
first (repeat . Right)(1999, 3)
([Right 1999,
Right 1999,
Right 1999, …] , 3)
10. 例
isModBy4 = (id &&& flip mod 4) >>> first (repeat . Right)
>>> first ((:) $ Left True) >>> uncurry (!!)
10
•(Int, Either Bool Int)から(Int, Either Bool Int)への関数。
•Left Trueの部分を見て、先ほど???だった部分がBoolだと分かる。
•Left xは、型Aの変数xを(Either A ???)型に変換する関数。
•:はリストに要素を結合する演算子。
x : xsで、リストxsの先頭にxがくっつけられる。
•演算子を()で囲むと関数になる。(:) x xsはx : xsと同じ意味。
Arrowでは関数を繋げていかないといけないので、関数化した。
first ((:) $ Left True)
([Left True,
Right 1999,
Right 1999, …] , 3)
([Right 1999,
Right 1999,
Right 1999, …] , 3)
11. 例
isModBy4 = (id &&& flip mod 4) >>> first (repeat . Right)
>>> first ((:) $ Left True) >>> uncurry (!!)
11
uncurry (!!) Right 1999
([Left True,
Right 1999,
Right 1999, …] , 3)
•(Int, Either Bool Int)からEither Bool Intへの関数。
•uncurryはf x yという関数をf (x,y)に変換する関数。
例えば(+)をuncurryすると、uncurry (+) (1, 3) = 4のような計算ができる。
•!!はリスト操作の演算子で、xs !! nとすると、リストxsのn番目の要素を
取り出す。
•受け渡されてくる値がペア型なので、uncurryした。
12. 考えてみよう
• isModBy4関数に整数を渡すと、場合によってBool型
やらInt型が求められるので、Either Bool Int型とした。
• しかし、結果を出力すると
Left TrueやらRight 1999
などと表示されてLeftとRightが鬱陶しい。
• そこで、結果を”True”、”1999”などとString型で統一
したい。isModBy4関数をどのように変更すれば良い
か?
12
isModBy4 = (id &&& flip mod 4) >>> first (repeat . Right)
>>> first ((:) $ Left True) >>> uncurry (!!)
15. Arrowの表示的意味論
• 実際、プログラムにおける(f *** g)はf×gでは表現できない。
• なぜなら、数学の世界において「fとgを直積集合C×C’の要素に
作用させる関数」は唯一つであり、それをf×gと表記しているの
に対し、(f *** g)はfとgの作用順が不明瞭なので、数学的に1つ
の関数で表現できない。
参考
C’
C
D’
D
f
g
fとgはどちらかが先に作用する
作用順によって2通りのパス
C×C’
C×D’
D×C’
D×D’
f
f
g g
15