如果我们完全颠倒一切,我们可以毫不奇怪地推导出Monad类似的东西。我们之前的声明和新的声明如下。我不完全确定下面定义的类实际上是集成,所以我不会这样明确地引用它。
如果 D t 是 t 的导数,则 D t 的乘积和恒等式是 Comonad
如果 D' t 是 ??? 的 t 那么 D' t 和恒等式的总和是 Monad
首先,我们将定义 a 的反义词Zipperan Unzipper。它将是一个总和,而不是一个产品。
data Zipper t a = Zipper { diff :: D t a , here :: a }
data Unzipper t a = Unzip (D' t a) | There a
AnUnzipper是 aFunctor只要D' t是 a Functor。
instance (Functor (D' t)) => Functor (Unzipper t) where
fmap f (There x) = There (f x)
fmap f (Unzip u) = Unzip (fmap f u)
如果我们回忆一下课堂Diff
class (Functor t, Functor (D t)) => Diff t where
type D t :: * -> *
up :: Zipper t a -> t a
down :: t a -> t (Zipper t a)
与它相反的事物类别Diff', 是相同的,但每个实例都Zipper替换为Unzipper并且箭头的顺序->翻转了。
class (Functor t, Functor (D' t)) => Diff' t where
type D' t :: * -> *
up' :: t a -> Unzipper t a
down' :: t (Unzipper t a) -> t a
如果我们使用我对上一个问题的解决方案
around :: (Diff t, Diff (D t)) => Zipper t a -> Zipper t (Zipper t a)
around z@(Zipper d h) = Zipper ctx z
where
ctx = fmap (\z' -> Zipper (up z') (here z')) (down d)
我们可以定义该函数的逆函数,它将join用于Monad.
inside :: (Diff' t, Diff' (D' t)) => Unzipper t (Unzipper t a) -> Unzipper t a
inside (There x) = x
inside (Unzip u) = Unzip . down' . fmap f $ u
where
f (There u') = There u'
f (Unzip u') = up' u'
这允许我们Monad为Unzipper.
instance (Diff' t, Diff' (D' t)) => Monad (Unzipper t) where
return = There
-- join = inside
x >>= f = inside . fmap f $ x
此实例Comonad与Zipper.
instance (Diff t, Diff (D t)) => Comonad (Zipper t) where
extract = here
duplicate = around