微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Scalaz:`scalaz.syntax.applicative._`是如何发挥作用的

这个问题与 this one有关,我试图了解如何在Scala中使用阅读器monad.

在答案中,autor使用以下代码获取ReaderInt [String]的实例:

import scalaz.Syntax.applicative._
val alwaysHello2: ReaderInt[String] = "hello".point[ReaderInt]

Scala使用哪种机制来解析表达式“hello”.point [ReaderInt]的类型,以便它使用正确的点函数

解决方法

每当你试图弄清楚这样的事情时,一个好的第一步是使用反射API去除表达式:

scala> import scalaz.Reader,scalaz.Syntax.applicative._
import scalaz.Reader
import scalaz.Syntax.applicative._

scala> import scala.reflect.runtime.universe.{ reify,showCode }
import scala.reflect.runtime.universe.{reify,showCode}

scala> type ReaderInt[A] = Reader[Int,A]
defined type alias ReaderInt

scala> showCode(reify("hello".point[ReaderInt]).tree)
res0: String = `package`.applicative.applicativeIdV("hello").point[$read.ReaderInt](Kleisli.kleisliIdMonadReader)

(您通常不希望在实际代码中使用scala.reflect.runtime,但对于像这样的调查来说它非常方便.)

当编译器看到你试图在没有point方法的类型上调用.point [ReaderInt]时 – 在这种情况下String-it开始查找将String转换为具有匹配点的类型的隐式转换方法(在Scala中称为“浓缩”).我们可以从showCode的输出中看到,它找到的隐式转换是在applicative语法对象中称为applicativeIdV的方法.

然后,它将此转换应用于String,从而生成applicativeIdV [String]类型的值.这种类型的point方法如下所示:

def point[F[_] : applicative]: F[A] = applicative[F].point(self)

对于像这样的东西,这是语法糖:

def point[F[_]](implicit F: applicative[F]): F[A] = F.point(self)

所以它需要做的下一件事就是为F找到一个applicative实例.在你的情况下,你明确指出F是ReaderInt.它解析了Reader [Int,_]的别名,它本身就是Kleisli [Id.Id,Int,并开始寻找实例.

它看起来的第一个地方之一将是Kleisli伴侣对象,因为它想要一个包含Kleisli的类型的隐式值,实际上showCode告诉我们它找到的那个是Kleisli.kleisliIdMonadReader.那时它就完成了,我们得到了我们想要的ReaderInt [String].

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐