是否存在逆变单子?

Zhe*_*lov 21 monads haskell category-theory

函数可以是协变的和逆变的.这种协变/逆变二元性也可以应用于monad吗?

就像是:

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
Run Code Online (Sandbox Code Playgroud)

请问ContraMonad类有意义吗?任何例子?

Mig*_*Mit 25

嗯,当然,可以定义它,但我怀疑它会有用.

有一种流行的说法是"monad只是一种类型的endofunctors中的幺半群".这意味着,首先,我们有一类endofunctors(意思是,从一些类别到其自身的(协变)函子),而且,我们在这个endofunctors上有一些乘法(在这种情况下 - 组合).然后monad适合我们现在不必担心的一般框架.关键是,逆变函子没有"乘法".两个协变仿函数的组合又是一个协变函子; 但是两个逆变函子的组合不是逆变函子(而是一个协变函子,所以,一个完全不同的野兽).

因此,"逆变单子"并不真正有意义.

  • 关于两个逆变的组成是协变的好点. (3认同)

lef*_*out 16

逆变函子是从一个类别到相反类别的仿函数,即从一个类别到另一个类别(尽管密切相关).OTOH,monad最重要的是一个endofunctor,即从一个类别到自身.所以它不能逆变.

当你考虑monad的"基本数学"定义时,这种东西总是更清晰:

class Functor m => Monad m where
  pure :: a -> m a
  join :: m (m a) -> m a
Run Code Online (Sandbox Code Playgroud)

如你所见,那里没有任何箭头你可以在结果中转身,就像你做的那样contrabind.当然有

class Functor n => Comonad n where
  extract :: n a -> a
  duplicate :: n a -> n (n a)
Run Code Online (Sandbox Code Playgroud)

但是comonads仍然是协变的函子.

不像单子,applicatives(monoidal函子)不需要endofunctors,所以我相信这些能够左右转动.让我们从"基本"定义开始:

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.
Run Code Online (Sandbox Code Playgroud)

(练习: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.
Run Code Online (Sandbox Code Playgroud)

不知道会有多大用处.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!
Run Code Online (Sandbox Code Playgroud)

我不认为这是有用的,尽管你可以用聪明的结合递归来定义它.

可能更有趣的是逆变的共幺体仿函数,但现在这对我来说太奇怪了.

  • 我相信ContraApp是可分的,它非常有用:https://hackage.haskell.org/package/contravariant-1.3.3/docs/Data-Functor-Contravariant-Divisible.html - 但它与你的有点不同得到了 (4认同)