Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用高级Scala功能实现半群的Scalaz_Scala_Traits_Implicits_Monoids_Semigroup - Fatal编程技术网

使用高级Scala功能实现半群的Scalaz

使用高级Scala功能实现半群的Scalaz,scala,traits,implicits,monoids,semigroup,Scala,Traits,Implicits,Monoids,Semigroup,我正在研究Scalaz中s的实现。我遇到了一个操作符,如果你在幺半群上定义append操作,它应该是现成的。此运算符的定义采用SemigroupSyntax。那个类通过一个函数得到幺半群 在检查了这三个类之后,我有一个主要问题-SemigroupSyntax的注释是如何实现的/**包装了一个值'self',并提供了与'Semigroup`*/ 隐式调用,这是一种神奇的方法。这是关于trait的,还有半群语法中的更多内容,我真的不明白 如果有人能抽出时间来启发我,我会很高兴的 提前谢谢你 编辑:

我正在研究Scalaz中s的实现。我遇到了一个操作符,如果你在幺半群上定义append操作,它应该是现成的。此运算符的定义采用SemigroupSyntax。那个类通过一个函数得到幺半群

在检查了这三个类之后,我有一个主要问题-SemigroupSyntax的注释是如何实现的
/**包装了一个值'self',并提供了与'Semigroup`*/

隐式调用
,这是一种神奇的方法。这是关于trait的
,还有半群语法中的更多内容,我真的不明白

如果有人能抽出时间来启发我,我会很高兴的

提前谢谢你

编辑:

我渴望了解本课程的工作原理:

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)

  ////
}
及其在半群中的调用位置:

val semigroupSyntax = new scalaz.syntax.SemigroupSyntax[F] { def F = Semigroup.this }

这里最让人迷惑的是,实际上有两条途径可以对对象进行操作

默认的第一个路由是通过
import scalaz.syntax.semigroup.\uz
。它为所有隐式可用的
半组
实例添加运算符

  • 任何
    半群
    实例都为自己创建一个
    半群语法
    的实现,用
    这个
    定义它的
    F
    方法
  • 在scalaz/syntax/package.scala中,有一个
    syntax
    singleton对象,它扩展了
    syntax
    trait。这是导入定义的第一部分
  • 在scalaz/syntax/syntax.scala中,在
    syntax
    中使用的
    trait中有一个
    semigroup
    单例对象,它扩展了
    到semigroupops
    。我们正在导入此对象的内容,仅包含隐式转换。转换的目的是捕获隐式提供的
    Semigroup
    实例,并构造一个包含所有操作的包装器
    SemigroupOps
  • 第二条路线是一个快捷方式,
    import[your\u semigroup\u instance].semigroupSyntax.\u
    ,是
    semigroup
    中的一个调用站点,您将被列出。它将运算符添加到一个特定的类型,对于该类型,
    半群
    实例为

  • semigroupSyntax
    semigroupSyntax
    特征的匿名实现,它的
    F
    方法被定义为
    Semigroup
    的特定实例
  • SemigroupSyntax
    trait本身,与
    ToSemigroupOps
    一样,提供了到
    SemigroupOps
    的隐式转换,但它不捕获隐式提供的实例,而是使用其
    F
    方法。因此,我们使用特定的
    半群
    类型类实现,得到类型
    F
    上的运算符

  • 如果你粘贴了你不懂的代码,这将更容易帮助你。谢谢你的详细解释。尽管我读了好几遍,我还是不太明白,但我有一些简单的问题。在你看来,图书馆设计师如何从这些误导中获益?它是关于代码可扩展性的吗?因为在我看来,这个东西是很难维护的。设计实际上是相当模块化的:每个类型类一个文件,另一个用于语法,在syntax.scala中有一个线性注册(加上,
    scalaz.std
    中的一些实例)。类型类及其语法包装器的代码遵循公共模式,虽然在Scalaz中没有使用,但它有一个通用的模式。虽然包装机制本身的设计非常类似于Haskell编码实践,看起来可能很复杂,但库体系结构仍然清晰且松散耦合。