Scalaz:`scalaz.syntax.applicative._` 如何发挥它的魔力 [英] Scalaz: how does `scalaz.syntax.applicative._` works its magic

查看:39
本文介绍了Scalaz:`scalaz.syntax.applicative._` 如何发挥它的魔力的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与这个问题有关,其中我试图了解如何在 Scala 中使用 reader monad.

This question is related to this one, where I was trying to understand how to use the reader monad in Scala.

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

In the answer the autor uses the following code for getting an instance of ReaderInt[String]:

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

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

Which mechanisms does Scala use to resolve the type of the expression "hello".point[ReaderInt] so that it uses the right point function?

推荐答案

每当您试图找出类似问题时,最好的第一步就是使用反射 API 来对表达式进行脱糖:

A good first step any time you're trying to figure out something like this is to use the reflection API to desugar the expression:

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,但它对于此类调查非常方便.)

(You generally don't want to use scala.reflect.runtime in real code, but it's extremely handy for investigations like this.)

当编译器发现您试图在没有 point 方法的类型上调用 .point[ReaderInt] 时——在本例中为 String——它开始寻找将 String 转换为具有匹配 point 方法的类型的隐式转换(这在 Scala 中称为浓缩").我们从showCode的输出中可以看出,它找到的隐式转换是applicative语法对象中名为ApplicativeIdV的方法.

When the compiler sees you trying to call .point[ReaderInt] on a type that doesn't have a point method—in this case String—it starts looking for implicit conversions that would convert a String into a type that does have a matching point method (this is called "enrichment" in Scala). We can see from the output of showCode that the implicit conversion it finds is a method called ApplicativeIdV in the applicative syntax object.

然后将这个转换应用到 String,产生 ApplicativeIdV[String] 类型的值.该类型的 point 方法如下所示:

It then applies this conversion to the String, resulting in a value of type ApplicativeIdV[String]. This type's point method looks like this:

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

以下内容的语法糖:

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

所以接下来需要做的是为 F 找到一个 Applicative 实例.在您的情况下,您已明确指定 FReaderInt.它将别名解析为 Reader[Int, _],它本身就是 Kleisli[Id.Id, Int, _] 的别名,并开始寻找实例.

So the next thing it needs to do is find an Applicative instance for F. In your case you've explicitly specified that F is ReaderInt. It resolves the alias to Reader[Int, _], which is itself an alias for Kleisli[Id.Id, Int, _], and starts looking for an instance.

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

One of the first places it looks will be the Kleisli companion object, since it wants an implicit value of a type that includes Kleisli, and in fact showCode tells us that the one it finds is Kleisli.kleisliIdMonadReader. At that point it's done, and we get the ReaderInt[String] we wanted.

这篇关于Scalaz:`scalaz.syntax.applicative._` 如何发挥它的魔力的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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