Kleisli、ReaderT和Reader在Scalaz中是相同的,这只是巧合吗

Kleisli、ReaderT和Reader在Scalaz中是相同的,这只是巧合吗,scala,scalaz,reader-monad,kleisli,Scala,Scalaz,Reader Monad,Kleisli,在斯卡拉兹 Kleisli[F,A,B]是A=>F[B]的包装器 ReaderT[F,A,B]——reader monad transformer——只是Kleisli[F,A,B]的别名 Reader[A,B]monad是ReaderT的一种专门化,具有标识monadId: 类型读取器[A,B]=ReaderT[Id,A,B] 这只是巧合还是有更深层次的原因使得Kleisli、ReaderT和Reader在Scalaz中是同构的 你可以把它看作是通过两条不同的路线到达同一个地方。一方面,您

在斯卡拉兹

  • Kleisli[F,A,B]
    A=>F[B]
    的包装器
  • ReaderT[F,A,B]
    ——reader monad transformer——只是
    Kleisli[F,A,B]
    的别名
  • Reader[A,B]
    monad是
    ReaderT
    的一种专门化,具有标识monad
    Id

    类型读取器[A,B]=ReaderT[Id,A,B]

这只是巧合还是有更深层次的原因使得
Kleisli
ReaderT
Reader
在Scalaz中是同构的

你可以把它看作是通过两条不同的路线到达同一个地方。一方面,您从reader monad开始,它只是一种函数包装器。然后,您意识到您想要将这个阅读器功能与其他“效果”集成到一个更大的monad中,因此您创建了一个
ReaderT
monad转换器。在这一点上,将原始的
Reader[E,?]
实现为
ReaderT[Id,E,?]
是有意义的

另一方面,您需要一个表示Kleisli箭头的类型(即具有一元返回类型的函数)。事实证明,这与
ReaderT
是一样的,所以您只需将其作为别名

“结果”部分并没有什么可怕的神秘之处。这有点像,如果你开始为类似数字的东西创建一个
Addable
类型类,然后决定使它更通用,最终创建一个只提供关联的“加法式”操作的类型类。您重新发明了
半群
!但是,出于历史或教学原因,或者只是为了方便起见,您可能仍然希望保留
可添加的
名称


这就是
Reader
ReaderT
所发生的一切-您不需要这些别名,但它们很方便,可能有助于提高代码的清晰度。

Reader和ReaderT/Kleisli不是同构的(正如您所说,前者是后者的特化)。@ZhekaKozlov谢谢。我错了(不过不会更新问题)。你可以在这里找到Travis解释的示例: