Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 阅读器monad-它如何符合monad接口?_Scala_Monads_Category Theory_Reader Monad - Fatal编程技术网

Scala 阅读器monad-它如何符合monad接口?

Scala 阅读器monad-它如何符合monad接口?,scala,monads,category-theory,reader-monad,Scala,Monads,Category Theory,Reader Monad,我在学习范畴理论。 我理解reader monad的概念,它甚至很容易实现: 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[DE

我在学习范畴理论。 我理解reader monad的概念,它甚至很容易实现:

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接口的约束

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]
}
让我们暂时忘记有一个applicative或functor,让我们把这3个方法放在这里

现在,有了这个接口,我在实现ReaderMonad时遇到了问题。 map方法非常简单,但纯平面地图又如何呢? 有纯粹的读者是什么意思? 为了实现flatMap,我需要一个从a到读取器[DEP,B]的函数,但是我有一个a=>Monad[B],因此我不可能访问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之类的库使用TypeClass来实现这些类型,但这只是出于教育目的。

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

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
是一个一元类型的构造函数,例如
List
Option
。您可以将
读取器[DEP,a]
视为一种计算,它依赖于某种环境类型
DEP
,该环境类型返回类型
a
的值。由于这有两个类型参数,因此在定义monad实例时需要修复环境参数类型:

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
用于部分应用
读取器[DEP,a]
的两个参数之一

现在
pure
返回一个
读取器
,该读取器忽略环境并直接返回给定值


flatMap
构造了一个
读取器
,当运行该读取器时,它将运行内部计算,使用结果构造下一个计算并在相同的环境下运行。

我将查看本机实现,并了解它们是如何实现的。如果你知道Haskell(即使你不知道),也许值得看看它的阅读器Monad的定义来寻找线索。好吧,它们使用完全不同的语法(主要是类型类),所以我不确定这是否会有帮助主要的问题是你的
Monad
特性是错误的,所以你不能真正实现它而不按你发现的那样强制转换。通常的实现是使用类型构造函数参数化
Monad
trait,并为
Reader[DEP,
@Lee定义它。你的意思是trait Monad[F[\u]]扩展函子[F]{def flatMap[a,B](fa:F[a])(F:a=>F[B])?是的,实例被隐式传递。谢谢!那个型号的lambda看起来…很有趣,至少。祝贺你获得了100K@尤瓦利扎科夫-谢谢!