[英]Scalaz, the purpose of *syntax classes
In scalaz when we define a module, we additionally define implicit, helper functions. 在我们定义模块的scalaz中,我们另外定义了隐式的辅助函数。 Here is an example of definition and how it could be used by a client:
以下是定义的示例以及客户端如何使用它:
trait Functor[F[_]] {
def map[A,B](fa: F[A])(f: A => B): F[B]
}
object Functor {
def fmap[F[_], A,B](as:F[A])(f:A=>B)
(implicit ff:Functor[F]):F[B] =
ff.map(as)(f)
implicit val listFunctor = new Functor[List] {
def map[A,B](as: List[A])(f: A => B): List[B] = as map f
}
}
...
import com.savdev.NewLibrary._
val r = fmap(List(1,2))(_.toString)
final class FunctorOps[F[_], A](self: F[A])(implicit ff:Functor[F]){
def qmap[B](f:A=>B):F[B] = ff.map(self)(f)
}
trait ToFunctorOps {
implicit def ToFunctorOps[F[_],A](v: F[A])(implicit F0: Functor[F]) =
new FunctorOps[F,A](v)
}
object NewLibrary extends ToFunctorOps
...
import com.savdev.NewLibrary._
val r2 = List(1, 4) qmap (x=>x.toString)
The code is slightly changed. 代码稍有改动。 But the idea is that we define:
但我们的想法是我们定义:
All above, the motivation of it and how it can be used by a client is clear. 以上所述,它的动机以及客户如何使用它是显而易见的。 But in
scalaz
to each such module definition, there is also a related *Syntax
class. 但是在每个这样的模块定义的
scalaz
中,还有一个相关的*Syntax
类。 I cannot understand the purpose of it. 我无法理解它的目的。 Can you please exlain, why it is needed and HOW it can be used in a client code.
请问exlain,为什么需要它以及如何在客户端代码中使用它。
In Scalaz it is defined as: 在Scalaz中,它被定义为:
trait FunctorSyntax[F[_]] {
implicit def ToFunctorOps[A](v: F[A]): FunctorOps[F, A] =
new FunctorOps[F, A](v)(FunctorSyntax.this.F)
def F: Functor[F]
}
UPDATED: 更新:
Guys, it seems I am not clear enough, or a topic is more complicated for all of us. 伙计们,似乎我不够清楚,或者对我们所有人来说,话题都更复杂。
What I need is to understand the difference between two traits: 我需要的是理解两个特征之间的区别:
trait ToFunctorOps {
implicit def ToFunctorOps[F[_],A](v: F[A])(implicit F0: Functor[F]) =
new FunctorOps[F,A](v)
}
vs. 与
trait FunctorSyntax[F[_]] {
implicit def ToFunctorOps[A](v: F[A]): FunctorOps[F, A] =
new FunctorOps[F, A](v)(FunctorSyntax.this.F)
def F: Functor[F]
}
Both traits define a generic method that creates FunctorOps
, both have the same visibility rules. 两个特征都定义了创建
FunctorOps
的通用方法,两者都具有相同的可见性规则。 The first ToFunctorOps
trait, it is not generic itself, it defines only generic method with [F[_],A]
. 第一个
ToFunctorOps
特性,它本身不是通用的,它只用[F[_],A]
定义泛型方法。 As a result, I can compose a lot of such traits into one object and import all of them at once. 结果,我可以将很多这样的特征组合成一个对象并一次导入所有这些特征。 I gave an example how such traits could be used by a client:
我举了一个例子,说明客户可以使用这些特征:
object NewLibrary extends ToFunctorOps
...
import com.savdev.NewLibrary._
val r2 = List(1, 4) qmap (x=>x.toString)
This trait already gives clients a possibility to inject methods implicitly. 这种特性已经为客户提供了隐式注入方法的可能性。 Why do we need
FunctorSyntax
? 为什么我们需要
FunctorSyntax
? This FunctorSyntax trait is a generic itself on [F[_]]
. 这个FunctorSyntax特征在
[F[_]]
上是一个通用的。 When I extend it, I must provide a type in the definition. 当我扩展它时,我必须在定义中提供一个类型。 Because
F[_]
now is used in trait definition, a function has less generic parameters, only [A]
. 因为
F[_]
现在用于特征定义,所以函数具有较少的泛型参数,仅[A]
。
I am asking you guys, if you can help and undestand, give me a code example how this FunctorSyntax
trait can be used by a client. 我问你们,如果你们可以提供帮助和解决,请给我一个代码示例,说明客户端如何使用
FunctorSyntax
特性。 Exactly this is not clear. 究竟这还不清楚。
Right now I see tries to explain the other topics, but not the original: 现在我看到尝试解释其他主题,但不是原来的:
ToFunctorOps
. ToFunctorOps
已提供此功能。 Guys, again, please show the community USE CASES via CODE of FunctorSyntax
. 伙计们,请再次
USE CASES via CODE of FunctorSyntax
向社区展示USE CASES via CODE of FunctorSyntax
。 Code itself is always the best documentation. 代码本身始终是最好的文档。
Best regards 最好的祝福
From what I can see in the scalaz codebase, I think that FunctorSyntax
is meant as an alternative way of enabling syntax. 从我在scalaz代码库中可以看到,我认为
FunctorSyntax
是一种启用语法的替代方法。 They define Functor
like this (simplified): 他们像这样定义
Functor
(简化):
trait Functor {
def map[A, B](fa: F[A])(f: A => B): F[B]
val functorSyntax = new FunctorSyntax[F] { def F = Functor.this }
}
This enables the following way of working: 这样可以实现以下工作方式:
def foo[F[_]](f: F[String])(implicit F: Functor[F]): F[Int] = {
import F.functorSyntax._
f.map(_.length)
}
Compare to how ToFunctorOps
adds syntax: 与
ToFunctorOps
添加语法的方式相比:
package scalaz.syntax { // simplified version of the scalaz codebase
object functor extends ToFunctorOps
}
import scalaz.syntax.functor._
def foo[F[_]: Functor](f: F[String]): F[Int] = f.map(_.length)
Here's a use case where you would use functorSyntax: 这是一个使用functorSyntax的用例:
import org.scalatest.{FreeSpec, Matchers}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scala.concurrent.duration._
import scalaz._
import Scalaz._
import scala.language.postfixOps
class ScalazTest extends FreeSpec with Matchers {
"compose functors" in {
val composedFunctor = Functor[Future] compose Functor[List] compose Functor[Option]
import composedFunctor.functorSyntax._
val actual = Future.successful(List(Some(1), Some(2), None, Some(4))) fmap (x => x * 2)
Await.result(actual, 10 seconds) shouldBe List(Some(2), Some(4), None, Some(8))
}
}
The idea is that you can compose several functor instaces and import the final composed functor's instance in scope and work with it. 这个想法是你可以组合几个函子实例并在范围内导入最终组成的仿函数实例并使用它。 Notice that
fmap
is resolved to composedFunctor.functorSyntax
in this case and it works on 3 levels of nesting ( Future[List[Option[Integer]]]
) while still accepting a function that deals with primitive types. 请注意,
fmap
决心composedFunctor.functorSyntax
在这种情况下,它的工作原理筑巢在3层( Future[List[Option[Integer]]]
同时还接受与原始类型的交易功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.