我有一个monad变压器:
newtype ChoiceT f m a = ChoiceT (forall x . f x -> m x) -> m a
现在我认为这是Monad
类别上的函子,我想为此绘制一个图
mapChoiceT ::
(n b -> m a)
-- ^ Function from one monad to another.
-- This is our morphism in the domain.
-> (ChoiceT f m a -> ChoiceT f n b)
-- ^ Function from lifted versions of the monads.
-- This is our morphism in the image
然而,这种实现方式使我逃脱了。我能够编写一个更简单的版本,其中n ~ m
:
lift2 ::
(m a -> m b)
-> (ChoiceT f m a -> ChoiceT f m b)
lift2 f m = ChoiceT (\ chooser -> f $ runChoiceT chooser m)
where
runChoiceT :: (forall x . f x -> m x) -> ChoiceT f m a -> m a
runChoiceT chooser (ChoiceT runner) = runner chooser
但是将其抽象化似乎超出了我。碰巧这可能是contravariant函子,这肯定会使编写协变量映射变得很困难,但我也没有运气写contramapChoiceT
。
mapChoiceT ::
(n b -> m a)
-- ^ Function from one monad to another.
-- This is our morphism in the domain.
-> (ChoiceT f m a -> ChoiceT f n b)
-- ^ Function from lifted versions of the monads.
-- This is our morphism in the image
此变压器是Monad
s类的函子吗?如果这是实现地图时我会出错的地方?如果不是,那有什么反例?
根据用于确定协方差的标准规则,“如果位置在偶数个箭头的左侧,则该位置是协变的。”通过检查ChoiceT
的签名,我们看到m
参数出现在对立和协变位置。因此,ChoiceT
在m
中是不变的。