有逆变单子吗?
Are there contravariant monads?
仿函数可以是协变的和逆变的。这种 covariant/contravariant 二元性也可以应用于单子吗?
类似于:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
class ContraMonad m where
return :: a -> m a
contrabind :: m a -> (b -> m a) -> m b
ContraMonad
class有意义吗?有例子吗?
逆变函子是从一个类别到其 opposite category 的函子,即从一个类别到另一个类别(尽管密切相关)的函子。 OTOH,monad 最重要的是 endofunctor,即从一个类别到 自身 。所以不可能是逆变的。
当你考虑 monad 的“基础数学”定义时,这类东西往往会更加清晰:
class Functor m => Monad m where
pure :: a -> m a
join :: m (m a) -> m a
如您所见,结果中并没有真正可以翻转的箭头,就像您对 contrabind
所做的那样。当然有
class Functor n => Comonad n where
extract :: n a -> a
duplicate :: n a -> n (n a)
但是共子仍然是协变函子。
与 monad 不同,applicatives (monoidal functors) 不需要是内函子,所以我相信这些 可以 被扭转。让我们从“基本”定义开始:
class Functor f => Monoidal f where
pureUnit :: () -> f ()
fzipWith :: ((a,b)->c) -> (f a, f b)->f c -- I avoid currying to make it clear what the arrows are.
(练习:根据 this 定义派生的 Applicative
实例,反之亦然)
扭转局面
class Contravariant f => ContraApp f where
pureDisunit :: f () -> ()
fcontraunzip :: ((a,b)->c) -> f c->(f a, f b)
-- I'm not sure, maybe this should
-- be `f c -> Either (f a) (f b)` instead.
不知道那会有多大用处。 pureDisunit
肯定没有用,因为它唯一的实现总是 const ()
.
让我们尝试编写明显的实例:
newtype Opp a b = Opp { getOpp :: b -> a }
instance Contravariant (Opp a) where
contramap f (Opp g) = Opp $ g . f
instance ContraApp (Opp a) where
pureDisunit = const ()
fcontraunzip z (Opp g)
= (Opp $ \a -> ???, Opp $ \b -> ???) -- `z` needs both `a` and `b`, can't get it!
我认为这没有用,尽管您可以使用诸如巧妙的打结递归之类的东西来定义它。
可能更有趣的是逆变共幺半群函子,但这现在对我来说太奇怪了。
嗯,当然可以定义它,但我怀疑它是否有用。
有一个流行的说法是"monad is just a monoid in a category of endofunctors"。它的意思是,首先,我们有一个内函子类别(意思是,从某个类别到它自己的(协变)函子),而且,我们在这个内函子上有一些乘法(在这种情况下 - 组合)。然后 monad 适合一些我们现在不必担心的通用框架。关键是,没有 "multiplication" 逆变函子。两个协变函子的组合又是一个协变函子;但是两个逆变函子的组合不是逆变函子(而是协变函子,所以是完全不同的野兽)。
所以,"contravariant monads"真的没有意义。
仿函数可以是协变的和逆变的。这种 covariant/contravariant 二元性也可以应用于单子吗?
类似于:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
class ContraMonad m where
return :: a -> m a
contrabind :: m a -> (b -> m a) -> m b
ContraMonad
class有意义吗?有例子吗?
逆变函子是从一个类别到其 opposite category 的函子,即从一个类别到另一个类别(尽管密切相关)的函子。 OTOH,monad 最重要的是 endofunctor,即从一个类别到 自身 。所以不可能是逆变的。
当你考虑 monad 的“基础数学”定义时,这类东西往往会更加清晰:
class Functor m => Monad m where
pure :: a -> m a
join :: m (m a) -> m a
如您所见,结果中并没有真正可以翻转的箭头,就像您对 contrabind
所做的那样。当然有
class Functor n => Comonad n where
extract :: n a -> a
duplicate :: n a -> n (n a)
但是共子仍然是协变函子。
与 monad 不同,applicatives (monoidal functors) 不需要是内函子,所以我相信这些 可以 被扭转。让我们从“基本”定义开始:
class Functor f => Monoidal f where
pureUnit :: () -> f ()
fzipWith :: ((a,b)->c) -> (f a, f b)->f c -- I avoid currying to make it clear what the arrows are.
(练习:根据 this 定义派生的 Applicative
实例,反之亦然)
扭转局面
class Contravariant f => ContraApp f where
pureDisunit :: f () -> ()
fcontraunzip :: ((a,b)->c) -> f c->(f a, f b)
-- I'm not sure, maybe this should
-- be `f c -> Either (f a) (f b)` instead.
不知道那会有多大用处。 pureDisunit
肯定没有用,因为它唯一的实现总是 const ()
.
让我们尝试编写明显的实例:
newtype Opp a b = Opp { getOpp :: b -> a }
instance Contravariant (Opp a) where
contramap f (Opp g) = Opp $ g . f
instance ContraApp (Opp a) where
pureDisunit = const ()
fcontraunzip z (Opp g)
= (Opp $ \a -> ???, Opp $ \b -> ???) -- `z` needs both `a` and `b`, can't get it!
我认为这没有用,尽管您可以使用诸如巧妙的打结递归之类的东西来定义它。
可能更有趣的是逆变共幺半群函子,但这现在对我来说太奇怪了。
嗯,当然可以定义它,但我怀疑它是否有用。
有一个流行的说法是"monad is just a monoid in a category of endofunctors"。它的意思是,首先,我们有一个内函子类别(意思是,从某个类别到它自己的(协变)函子),而且,我们在这个内函子上有一些乘法(在这种情况下 - 组合)。然后 monad 适合一些我们现在不必担心的通用框架。关键是,没有 "multiplication" 逆变函子。两个协变函子的组合又是一个协变函子;但是两个逆变函子的组合不是逆变函子(而是协变函子,所以是完全不同的野兽)。
所以,"contravariant monads"真的没有意义。