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]
——reader monad transformer——只是ReaderT[F,A,B]
的别名李>Kleisli[F,A,B]
monad是Reader[A,B]
的一种专门化,具有标识monadReaderT
: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解释的示例: