9

我尝试学习/理解一点 scalaz。为此,我从示例开始:

List(3, 4, 5).asMA.foldMap(x => x)
 => 12 //(3+4+5) 

def foldMap[B](f: A => B)(implicit r: Foldable[M], m: Monoid[B])

所以某处必须是一个 Foldable[List[_]] 和一个 Monoid[Int] (附加 = + 和零 = 0)。但我无法找到这两个隐式。有没有简单的方法可以找到它们?

然后下一个例子是:

List(3, 4, 5).asMA.foldMap(multiplication)
 => 60 //(3*4*5)

在这里,我变得更加困惑。我假设乘法必须将 Monoid[Int] 替换为 append = *, zero = 1 的一个。但是 f: A=>B 丢失了。如果我遵循乘法,我找不到任何与 Monoid 或函数等相关的东西。

sealed trait IntMultiplication extends NewType[Int]

trait NewType[X] {
  val value: X
  override def toString = value.toString
}
4

2 回答 2

9

处理隐式时有一些方便的编译器标志-Xlog-implicits-Xprint:typer-Ytyper-debug

在这种情况下,您可以使用-Xprint:typerflag 查看具有应用隐式的表达式。然后,第一个片段List(3, 4, 5).asMA.foldMap(identity)将扩展为

scalaz.this.Scalaz.SeqMA[List, Int](immutable.this.List.apply[Int](3, 4, 5)).asMA.foldMap[Int]({
  ((x: Int) => scala.this.Predef.identity[Int](x))
})(scalaz.this.Foldable.ListFoldable,
   scalaz.this.Monoid.monoid[Int](scalaz.this.Semigroup.IntSemigroup, scalaz.this.Zero.IntZero));

现在很明显

Monoid.monoid[Int](Semigroup.IntSemigroup, Zero.IntZero)

用于创建Monoid[Int]实例(附加 = + 和零 = 0)

第二个片段,List(3, 4, 5).foldMap(multiplication)将扩展为

scalaz.this.Scalaz.SeqMA[List, Int](immutable.this.List.apply[Int](3, 4, 5)).foldMap[scalaz.IntMultiplication]({
  ((n: Int) => scalaz.Scalaz.multiplication(n))
})(scalaz.this.Foldable.ListFoldable,
   scalaz.this.Monoid.monoid[scalaz.IntMultiplication](scalaz.this.Semigroup.IntMultiplicationSemigroup, scalaz.this.Zero.IntMultiplicationZero));

在这种情况下Monoid[IntMultiplication](附加 = * 和零 = 1)用作隐式参数。

更新

Monoid为您的类型创建,您需要具有隐式SemigroupZero范围内

case class Foo(x: Int)

implicit def FooSemigroup: Semigroup[Foo] = semigroup((f1, f2) => Foo(f1.x + f2.x))
implicit def FooZero: Zero[Foo] = zero(Foo(0))

scala> (1 to 10) map Foo foldMap identity
res5: Foo = Foo(55)
于 2012-05-01T09:20:37.530 回答
7

Scalaz 6 将类型类实例存储在类型类本身的伴随对象中,因此您需要查看那里。

在 Monoid[T] 的情况下,实际的类型类可分为两部分: Semigroup[T] 为我们提供了附加操作 (T, T) => T,Zero[T] 为我们提供了一个零函数: () => T. 然后可以通过位于 MonoidLow 中的隐式 def monoid 生成实际的 Monoid 实例。

对于 foldable,Foldable[List] 的类型类位于 Foldable 单例中,称为 ListFoldable。

我相信你已经解决了,整数范围内的默认幺半群是 (+, 0),所以你在第二个例子中使用的乘法函数只是包装器类型 IntMultiplication 的转换器,它具有半群以及在相关伴随对象中定义的零个实例。

如果你想了解 Scalaz,这里有几个很好的介绍视频。我发现最有用的是这两个:

[1] http://skillsmatter.com/podcast/scala/practical-scalaz-2518/js-1603

[2] http://www.infoq.com/presentations/Scalaz-Functional-Programming-in-Scala#.T0q_hgmiJbw.wordpress

两者都涉及到幺半群。

于 2012-05-01T09:11:52.887 回答