generated at
Arrow型クラス
John Hughesによって定義された

computationを圏論の文脈で呼ぶと射(arrow)となる
なので、>>>は「computationとcomputationの合成」と言っても、「arrowとarrowの合成」と言っても正しい

全てのモナドはArrowに変換できる
モナドで済む場合は、モナドを使うべき
モナドに似ているが、モナドではないときはArrowを使えばいい


ノリだけ思い出したければこれを読めばいいmrsekut


関数を計算に変換する機能と 2 つの計算を並列に実行する計算を作る機能を兼ね備えたのが Arrow クラス
つまり、Category型クラス+並行計算?
Category型クラスを継承する必要がる


Monad型クラスの一般化
複数の入力を消費できる
入力値による選択が行える
フィードバックが可能である



定義
hs
class Category h => Arrow h where -- 関数を計算へ持ち上げ arr :: (a -> b) -> h a b (***) :: h a b -> h c d -> h (a, c) (b, d) first :: h a b -> h (a,c) (b,c) first = (*** id) second :: h a b -> h (c,a) (c,b) second = (id ***)
first
first f = f *** id と同じ
よくわかっていないmrsekut
hs
first (arr f) = arr (f >< id) -- 拡張 first (f >>> g) = first f >>> first g -- 関手 first f >>> arr (id >< g) = arr (id >< g) >>> first f -- 交換 first f >>> arr fst = arr fst >>> f -- 単位 first (first f) >>> arr assoc = arr assoc first f -- 結合
seocnd
second = (id ***) と同じ


ミニマムな定義
上の定義では、 *** second も個別に定義しているが、
arr first があれば実装できる
hs
second :: h b c -> h (d, b) (d, c) seconf f = (arr swap) . (first f) . (arr swap) where swap ~(x, y) = (y, x) (***) :: h b c -> h b' c' -> h (b, b') (c, c') f *** g = (first f) . (second g)



&&&も定義されている
計算に適用する前に入力を複製する
hs
(&&&) :: h a b -> h a b' -> h a (b,b') f &&& g = arr (\b -> (b,b)) >>> f *** g



インスタンス
普通の関数 (->)
hs
instance Arrow (->) where arr f = f (***) f g ~(x,y) = (f x, g y)
hs
instance Monad m => Arrow (Kleisli m) where -- 関数を計算へ持ち上げ arr :: (a -> b) -> (a -> m b) arr f = return . f -- 計算を並列実行する計算を作成 (***) :: (a -> m b) -> (c -> m d) -> ((a, c) -> m (b, d)) f *** g = \(x, y) -> do {s <- f x; t <- g y; return (s, t)}


使用例
普通の関数 (->)
hs
plus1 = (+1) double = (*2) (plus1 *** double) (10,10) -- >> (11,20) first plus1 (10,10) -- >> (11,10) second double (10,10) -- >> (10,20)



Arrowを継承した型クラス


いつ嬉しい?
タプルってそんな使わなくね?という気持ちがあるが、そんなに嬉しいのか?



ユースケース


参考
最初に読むのにすごく良い
敢えて関数名とか定義とずらしているんだろうけど、逆に混乱を招く感じもするmrsekut
『関数プログラミングの楽しみ』10章の内容から取ってきている
Categoryの (.) など(記事内では >>> )が微妙に型がズレているので注意mrsekut

arrowとLens