使用高级 Scala 功能的 Semigroup 的 Scalaz 实现
Scalaz implementation of Semigroup using advanced Scala features
我正在研究 Monoids in Scalaz. I came across the |+| operator that is supposed to come out of the box if you define the append operation on Monoid. The definition of this operator is in SemigroupSyntax. That class gets to Monoid through Semigroup 的实现。
在检查了这三个 classes 之后,我有一个主要问题 - 来自 SemigroupSyntax 的评论究竟是如何实现的 /** Wraps a value `self` and provides methods related to `Semigroup` */
隐含函数有一些魔力,在特征上调用 .this
以及 SemigroupSyntax 中的更多内容,老实说我不明白。
如果有人能花时间开导我,我会很高兴。
提前致谢!
编辑:
我很想了解这个 class 的工作原理:
package scalaz
package syntax
/** Wraps a value `self` and provides methods related to `Semigroup` */
final class SemigroupOps[F] private[syntax](val self: F)(implicit val F: Semigroup[F]) extends Ops[F] {
////
final def |+|(other: => F): F = F.append(self, other)
final def mappend(other: => F): F = F.append(self, other)
final def ⊹(other: => F): F = F.append(self, other)
////
}
trait ToSemigroupOps {
implicit def ToSemigroupOps[F](v: F)(implicit F0: Semigroup[F]) =
new SemigroupOps[F](v)
////
////
}
trait SemigroupSyntax[F] {
implicit def ToSemigroupOps(v: F): SemigroupOps[F] = new SemigroupOps[F](v)(SemigroupSyntax.this.F)
def F: Semigroup[F]
////
def mappend(f1: F, f2: => F)(implicit F: Semigroup[F]): F = F.append(f1, f2)
////
}
及其在Semigroup的调用站点:
val semigroupSyntax = new scalaz.syntax.SemigroupSyntax[F] { def F = Semigroup.this }
这里最让人迷惑的是实际上有两条途径可以获取对象上的操作。
第一条路线,默认路线,import scalaz.syntax.semigroup._
。它为所有隐式可用的 Semigroup
个实例添加运算符。
- 任何
Semigroup
实例都会为自己创建 SemigroupSyntax
的实现,根据 this
. 定义其 F
方法
- 在 scalaz/syntax/package.scala 中,有一个
syntax
单例对象扩展了 Syntaxes
特征。这是导入定义的第一部分。
- 在 scalaz/syntax/Syntax.scala 中,在
syntax
中使用的 Syntaxes
特征中有一个 semigroup
单例对象,它扩展了 ToSemigroupOps
。我们正在导入此对象的内容,仅包含隐式转换。转换的目的是捕获隐式提供的 Semigroup
实例并构造一个包装器 SemigroupOps
,其中包含所有操作。
第二条路线是 import [your_semigroup_instance].semigroupSyntax._
的捷径,Semigroup
中的一个呼叫站点已列出。它将运算符添加到特定类型,Semigroup
实例是。
semigroupSyntax
是 SemigroupSyntax
特性的匿名实现,其中 F
方法被定义为 Semigroup
. 的特定实例
SemigroupSyntax
trait 本身与 ToSemigroupOps
一样,提供到 SemigroupOps
的隐式转换,但它不是捕获隐式提供的实例,而是使用其 F
方法。因此,我们使用特定的 Semigroup
类型类实现获得 F
类型的运算符。
我正在研究 Monoids in Scalaz. I came across the |+| operator that is supposed to come out of the box if you define the append operation on Monoid. The definition of this operator is in SemigroupSyntax. That class gets to Monoid through Semigroup 的实现。
在检查了这三个 classes 之后,我有一个主要问题 - 来自 SemigroupSyntax 的评论究竟是如何实现的 /** Wraps a value `self` and provides methods related to `Semigroup` */
隐含函数有一些魔力,在特征上调用 .this
以及 SemigroupSyntax 中的更多内容,老实说我不明白。
如果有人能花时间开导我,我会很高兴。
提前致谢!
编辑:
我很想了解这个 class 的工作原理:
package scalaz
package syntax
/** Wraps a value `self` and provides methods related to `Semigroup` */
final class SemigroupOps[F] private[syntax](val self: F)(implicit val F: Semigroup[F]) extends Ops[F] {
////
final def |+|(other: => F): F = F.append(self, other)
final def mappend(other: => F): F = F.append(self, other)
final def ⊹(other: => F): F = F.append(self, other)
////
}
trait ToSemigroupOps {
implicit def ToSemigroupOps[F](v: F)(implicit F0: Semigroup[F]) =
new SemigroupOps[F](v)
////
////
}
trait SemigroupSyntax[F] {
implicit def ToSemigroupOps(v: F): SemigroupOps[F] = new SemigroupOps[F](v)(SemigroupSyntax.this.F)
def F: Semigroup[F]
////
def mappend(f1: F, f2: => F)(implicit F: Semigroup[F]): F = F.append(f1, f2)
////
}
及其在Semigroup的调用站点:
val semigroupSyntax = new scalaz.syntax.SemigroupSyntax[F] { def F = Semigroup.this }
这里最让人迷惑的是实际上有两条途径可以获取对象上的操作。
第一条路线,默认路线,import scalaz.syntax.semigroup._
。它为所有隐式可用的 Semigroup
个实例添加运算符。
- 任何
Semigroup
实例都会为自己创建SemigroupSyntax
的实现,根据this
. 定义其 - 在 scalaz/syntax/package.scala 中,有一个
syntax
单例对象扩展了Syntaxes
特征。这是导入定义的第一部分。 - 在 scalaz/syntax/Syntax.scala 中,在
syntax
中使用的Syntaxes
特征中有一个semigroup
单例对象,它扩展了ToSemigroupOps
。我们正在导入此对象的内容,仅包含隐式转换。转换的目的是捕获隐式提供的Semigroup
实例并构造一个包装器SemigroupOps
,其中包含所有操作。
F
方法
第二条路线是 import [your_semigroup_instance].semigroupSyntax._
的捷径,Semigroup
中的一个呼叫站点已列出。它将运算符添加到特定类型,Semigroup
实例是。
semigroupSyntax
是SemigroupSyntax
特性的匿名实现,其中F
方法被定义为Semigroup
. 的特定实例
SemigroupSyntax
trait 本身与ToSemigroupOps
一样,提供到SemigroupOps
的隐式转换,但它不是捕获隐式提供的实例,而是使用其F
方法。因此,我们使用特定的Semigroup
类型类实现获得F
类型的运算符。