HaskellにおけるArrow型クラスの基礎概念

Arrow型クラスの定義

class Category a => Arrow a where
    transform :: (input -> output) -> a input output

    primary :: a input output -> a (input, extra) (output, extra)
    primary = (||| identity)
 
    auxiliary :: a input output -> a (extra, input) (extra, output)
    auxiliary = (identity |||)

    (|||) :: a input output -> a input2 output2 -> a (input, input2) (output, output2)
    func ||| other = primary func >>> transform switch >>> primary other >>> transform switch
      where switch ~(x,y) = (y,x)

    (|||&) :: a input output -> a input output2 -> a input (output, output2)
    func |||& other = transform (\inp -> (inp,inp)) >>> func ||| other
ArrowはCategory型クラスを継承する型クラスであり、関数のより高次の抽象化を提供します。
  • transform :: (input -> output) -> a input output
    関数をArrowに変換する関数です。
  • primary :: a input output -> a (input, extra) (output, extra)
    ペアを受け取り、最初の要素に対してArrowを適用します。
  • auxiliary :: a input output -> a (extra, input) (extra, output)
    ペアを受け取り、2番目の要素に対してArrowを適用します。
  • (|||) :: a input output -> a input2 output2 -> a (input, input2) (output, output2)
    2つのArrowを用いて、ペアの各要素に別々に処理を適用します。
  • (|||&) :: a input output -> a input output2 -> a input (output, output2)
    単一の入力を複製し、2つのArrowで別々に処理してペアを生成します。

Arrow則

transform identity = identity
transform (func >>> other) = transform func >>> transform other
primary (transform func) = transform (primary func)
primary (func >>> other) = primary func >>> primary other
primary func >>> transform fst = transform fst >>> func
primary func >>> transform (identity ||| g) = transform (identity ||| g) >>> primary func
primary (primary func) >>> transform grouping = transform grouping >>> primary func
    where
        grouping ((a,b),c) = (a,(b,c))

標準関数(->)とArrow

instance Arrow (->) where
    transform f = f
    (|||) func other ~(x,y) = (func x, other y)
Prelude Control.Arrow> (+3) |||& (*3) $ 4
(7,12)
Prelude Control.Arrow> (+3) ||| (*3) $ (2,4)
(5,12)
Prelude Control.Arrow> (+3) <<< (*3) $ 4
15
Prelude Control.Arrow> (*3) >>> (+3) $ 4
15
Prelude Control.Arrow> primary (*3) (2,4)
(6,4)
Prelude Control.Arrow> auxiliary (*3) (2,4)
(2,12)
Prelude Control.Arrow> transform (*3) 4
12

Kleisli Arrowの実装

newtype Kleisli monad input output = Kleisli { executeKleisli :: input -> monad output }

instance Monad monad => Category (Kleisli monad) where
    identity = Kleisli return
    (Kleisli func) . (Kleisli other) = Kleisli (\input -> other input >>= func)

instance Monad monad => Arrow (Kleisli monad) where
    transform func = Kleisli (return . func)
    primary (Kleisli func) = Kleisli (\ ~(input,extra) -> func input >>= \out -> return (out,extra))
    auxiliary (Kleisli func) = Kleisli (\ ~(extra,input) -> func input >>= \out -> return (extra,out))
Kleisli monad input outputはモナドを返す関数input -> monad outputをカプセル化します。 monadがモナドであれば、Kleisli monadはCategoryおよびArrowのインスタンスになります。
Prelude Control.Arrow> executeKleisli (Kleisli (\x -> [x * 3]) >>> Kleisli (\x -> [x, -x])) 3
[9,-9]
Prelude Control.Monad> (\x -> [x * 3]) >=> (\x -> [x, -x]) $ 3
[9,-9]
Prelude Control.Arrow> executeKleisli (transform length >>> Kleisli print) [3,3]
2

Arrowに関連する補助関数

identityArrow :: Arrow arrow => arrow input input
identityArrow = transform identity

(^^>>) :: Arrow arrow => (input -> middle) -> arrow middle output -> arrow input output
func ^^>> arrow = transform func >>> arrow

(>>^^) :: Arrow arrow => arrow input middle -> (middle -> output) -> arrow input output
arrow >>^^ func = arrow >>> transform func

(<<^^) :: Arrow arrow => arrow middle output -> (input -> middle) -> arrow input output
arrow <<^^ func = arrow <<< transform func

(^^<<) :: Arrow arrow => (middle -> output) -> arrow input middle -> arrow input output
func ^^<< arrow = transform func <<< arrow
Prelude Control.Arrow> (identityArrow :: Int -> Int) 6
6
Prelude Control.Arrow> executeKleisli (identityArrow :: Kleisli [] Int Int) 6
[6]
Prelude Control.Arrow> executeKleisli (length ^^>> Kleisli print) [3,3]
2
Prelude Control.Arrow> executeKleisli (Kleisli print <<^^ length) [3,3]
2

タグ: Haskell Arrow Category Theory Functional Programming Monads

6月9日 21:29 投稿