如何解决什么是单子类的函子?
请注意,这个问题与“ endofunctors类别中的monoids”无关。也不是直接与
Functor
有关(Monad
始终是Functor
,但是这个问题主要涉及monad变换器)
Haskell的SelectT
monad变压器上的docs指出
SelectT
不是单子类的函子,并且无法通过它进行许多操作。
- 单子的类别是什么?该类别中的箭头是什么?
- 为什么有些monad变换器的仿函数(例如
MaybeT
,RWST
等,而有些不是ContT
,SelectT
)呢? - 从编程的角度来看,成为单子类别的函子有什么用?为什么我应该作为图书馆的消费者呢?
解决方法
- 单子的类别是什么?该类别中的箭头是什么?
对象是单子对象的类别,即类型为T
的{{1}}类型为Type -> Type
的类型Monad
,箭头A -> B
是自然变换在其底层函子之间,通常用forall x. A x -> B x
类型的函数在Haskell中表示(尽管严格地说,参数性比自然性更强)。
mmorph软件包中有此实现。
此类别的初始对象为Identity
,因为对于任何单子T
而言,都只有一个自然变换forall x. Identity x -> T x
。双重地,我认为最终对象是Const ()
。
- 为什么有些monad变换器的仿函数(例如
MaybeT
,RWST
等,而有些不是ContT
,SelectT
)呢?
此类别的函子需要解除fmap
:
fmap'
:: forall m n. (Monad m,Monad n)
=> (forall x. m x -> n x) -> forall x. T m x -> T n x
并且您通常无法在ContT
和SelectT
上实现此功能。我不确定为什么会这样,但是它似乎取决于方差:我们正在尝试实现协变函子,但是ContT
和SelectT
是不变的在其基本单子中,例如m
在(a -> m r) -> m r
内的ContT r m a
中正反两面地出现。
- 从编程的角度来看,成为单子类别的函子有什么用?为什么我应该作为图书馆的消费者呢?
如果您有一般的方式可以在单子m
中“运行”单子n
,则不必将其提升为ContT
或SelectT
;您会受制于更严格的映射操作,如下所示:
mapSelectT :: (m a -> m a) -> SelectT r m a -> SelectT r m a
mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
基本monad和结果类型固定的位置。因此,您无法始终在使用这些转换器的堆栈中自由地提升动作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。