使用高级 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 个实例添加运算符。

  1. 任何 Semigroup 实例都会为自己创建 SemigroupSyntax 的实现,根据 this.
  2. 定义其 F 方法
  3. 在 scalaz/syntax/package.scala 中,有一个 syntax 单例对象扩展了 Syntaxes 特征。这是导入定义的第一部分。
  4. 在 scalaz/syntax/Syntax.scala 中,在 syntax 中使用的 Syntaxes 特征中有一个 semigroup 单例对象,它扩展了 ToSemigroupOps。我们正在导入此对象的内容,仅包含隐式转换。转换的目的是捕获隐式提供的 Semigroup 实例并构造一个包装器 SemigroupOps,其中包含所有操作。

第二条路线是 import [your_semigroup_instance].semigroupSyntax._ 的捷径,Semigroup 中的一个呼叫站点已列出。它将运算符添加到特定类型,Semigroup 实例是。

  1. semigroupSyntaxSemigroupSyntax 特性的匿名实现,其中 F 方法被定义为 Semigroup.
  2. 的特定实例
  3. SemigroupSyntax trait 本身与 ToSemigroupOps 一样,提供到 SemigroupOps 的隐式转换,但它不是捕获隐式提供的实例,而是使用其 F 方法。因此,我们使用特定的 Semigroup 类型类实现获得 F 类型的运算符。