HaskellのProfunctor概念と実装例

Profunctorの定義

class Profunctor p where
  dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
  dimap f g = lmap f . rmap g
  
  lmap :: (a -> b) -> p b c -> p a c
  lmap f = dimap f id
  
  rmap :: (b -> c) -> p a b -> p a c
  rmap = dimap id

Profunctorは2つの型パラメータを持つ型クラスで、第1引数が反変(contravariant)、第2引数が共変(covariant)な性質を持ちます。主要な関数は以下の通り:

  • dimap: 双方向の変換を行い、Profunctorの両パラメータを同時に変更
  • lmap: 左側(反変)パラメータのみを変換
  • rmap: 右側(共変)パラメータのみを変換

Profunctorは入出力の概念を一般化し、p b cにおいて入力bは反変、出力cは共変として振る舞います。

Profunctor則

-- 基本法則
dimap id id ≡ id
lmap id ≡ id
rmap id ≡ id
dimap f g ≡ lmap f . rmap g

-- 派生法則
dimap (f . g) (h . i) ≡ dimap g h . dimap f i
lmap (f . g) ≡ lmap g . lmap f
rmap (f . g) ≡ rmap f . rmap g

関数型のProfunctorインスタンス

instance Profunctor (->) where
  dimap pre post fn = post . fn . pre
  lmap pre fn = fn . pre
  rmap = (.)
ghci> lmap (+2) (*3) 4  -- (4+2)*3 = 18
18
ghci> rmap (+3) (*3) 4 -- 4*3+3 = 15
15
ghci> dimap (+2) (+3) (*3) 4 -- (4+2)*3+3 = 21
21

関数型(->)は典型的なProfunctorであり、dimap (+2) (+3) (*3)(+3) . (*3) . (+2)と等価です。

Star型のProfunctor実装

newtype Star f d c = Star { runStar :: d -> f c }

instance Functor f => Profunctor (Star f) where
  dimap pre post (Star fn) = Star (fmap post . fn . pre)
  lmap k (Star f) = Star (f . k)
  rmap k (Star f) = Star (fmap k . f)

StarはFunctorをProfunctorに変換します。実装例:

ghci> runStar (dimap (+1) show (Star Just)) 5 
Just "6"  -- fmap show . Just . (+1) $ 5

Costar型のProfunctor実装

newtype Costar f d c = Costar { runCostar :: f d -> c }

instance Functor f => Profunctor (Costar f) where
  dimap pre post (Costar fn) = Costar (post . fn . fmap pre)
  lmap k (Costar f) = Costar (f . fmap k)
  rmap k (Costar f) = Costar (k . f)
ghci> runCostar (dimap (+1) show (Costar sum)) [1,2,3]
"9"  -- show . sum . fmap (+1) $ [1,2,3]

Forget型のProfunctor実装

newtype Forget r a b = Forget { runForget :: a -> r }

instance Profunctor (Forget r) where
  dimap pre _ (Forget k) = Forget (k . pre)
  lmap pre (Forget k) = Forget (k . pre)
  rmap _ (Forget k) = Forget k

タグ: Haskell Profunctor 型クラス 関手 圏論

5月18日 10:05 投稿