Reader Monad-它如何符合Monad界面? [英] Reader monad - how does it conform to Monad interface?

查看:129
本文介绍了Reader Monad-它如何符合Monad界面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习类别理论. 我了解阅读器monad的概念,它甚至很容易实现:

I'm learning category theory. I understand the concept of reader monad, it's even pretty easy to implement:

case class Reader[DEP, A](g: DEP => A) {
  def apply(dep: DEP): A = g(dep)

  def map[B](f: A => B): Reader[DEP, B] = Reader(dep => f(apply(dep)))

  def flatMap[B](f: A => Reader[DEP, B]): Reader[DEP, B] = Reader(dep => f(apply(dep)) apply dep)
}

但是,在对某些通用Monad接口(即

However, I have problems implementing it with constraint to some generic Monad interface, i.e

trait Monad[A] {
  def pure(a: A): Monad[A]

  def map[B](f: A => B): Monad[B]

  def flatMap[B](f: A => Monad[B]): Monad[B]
}

让我们忘记了一个应用程序或函子,让我们将这三种方法放在这里.

let's forgot for a second that there's an applicative or functor and let's just put these 3 methods here.

现在,有了这个接口,我在实现ReaderMonad时遇到了问题. map方法很简单,但是pure和flatMap呢? 在Reader上拥有纯文本甚至意味着什么? 要实现flatMap,我需要有一个从A到Reader [DEP,B]的函数,但是我有A => Monad [B],因此无法访问apply.

Now, having this interface I have problems implementing ReaderMonad. map method is pretty straighforward, but what about pure and flatMap? What does it even mean to have pure on Reader? To implement flatMap, I need to have a function from A to Reader[DEP, B], but I have A => Monad[B], thus I'm not possible to access apply.

case class Reader[DEP, A](g: DEP => A) extends Monad[A] {
  def apply(dep: DEP): A = g(dep)

  override def pure(a: A): Reader[DEP, A] = Reader(_ => a) // what does it even mean in case of Reader

  override def map[B](f: (A) => B): Reader[DEP, B] = Reader(dep => f(apply(dep)))

  override def flatMap[B](f: (A) => Monad[B]): Reader[DEP, B] = ??? // to implement it, I need f to be (A) => Reader[DEP, B], not (A) => Monad[B]
}

是否可以在scala中以这种方式实现它?我尝试使用自绑定类型,但是它也不起作用. 我知道像scalaz或cats这样的库都使用类型类来实现这些类型,但这只是出于教育目的.

Is it possible to implement it this way in scala? I tried to play around with self bound types, but it didn't work either. I know libraries like scalaz or cats uses typeclasses to implement these types, but this is just for educational purpose.

推荐答案

正如您在尝试实现flatMap时所发现的那样,在声明Monad特性时存在的问题是您丢失了特定的monad类型在定义何时进行链接操作.定义Monad特质的通常方法是通过类型构造函数对其进行参数化,例如,为之定义monad实例.

As you've discovered when trying to implement flatMap, the problem with declaring the Monad trait as you have is you lose the particular monad type you're defining when chaining operations. The usual way of defining the Monad trait is to parameterise it by the type constructor the monad instance is being defined for e.g.

trait Monad[M[_]] {
    def pure[A](a: A): M[A]
    def map[A, B](f: A => B, m: M[A]): M[B]
    def flatMap[A, B](f: A => M[B], m : M[A]): M[B]
}

所以M是一元类型构造函数,例如ListOption.您可以将Reader[DEP, A]视为取决于某些环境类型DEP的计算,该环境类型返回值A.由于它具有两个类型参数,因此在定义monad实例时需要修复环境参数类型:

So M is a unary type constructor such as List or Option. You can think of a Reader[DEP, A] as being a computation which depends on some environment type DEP which returns a value of type A. Since this has two type parameters you need to fix the environment parameter type when defining the monad instance:

case class Reader[DEP, A](g: DEP => A)

class ReaderMonad[DEP]() extends Monad[({type t[X] = Reader[DEP, X]})#t] {
    def pure[A](a: A) = Reader[DEP, A](_ => a)
    def map[A, B](f: A => B,m: Reader[DEP,A]): Reader[DEP,B] = Reader(env => f(m.g(env)))
    def flatMap[A, B](f: A => Reader[DEP,B],m: Reader[DEP,A]): Reader[DEP,B] = Reader(env => f(m.g(env)).g(env))
}

({type t[X] = Reader[DEP, X]})#t类型lambda ,用于部分地将两个参数之一应用于Reader[DEP, A].

({type t[X] = Reader[DEP, X]})#t is a type lambda used to partially apply one of the two parameters for Reader[DEP, A].

现在pure返回一个Reader,它忽略环境并直接返回给定值.

Now pure returns a Reader which ignores the environment and returns the given value directly.

flatMap构造一个Reader,运行时将运行内部计算,并使用结果构造下一个计算并在相同的环境下运行它.

flatMap constructs a Reader which when run will run the inner computation, use the result to construct the next computation and run it with the same environment.

这篇关于Reader Monad-它如何符合Monad界面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆