我尝试学习/了解一点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])
Run Code Online (Sandbox Code Playgroud)
所以某处必须是可折叠的[List [_]]和Monoid [Int](附加= +和0 = 0).但我无法找到这两个含义.有没有一种简单的方法可以找到它们?
然后下一个例子是:
List(3, 4, 5).asMA.foldMap(multiplication)
=> 60 //(3*4*5)
Run Code Online (Sandbox Code Playgroud)
在这里,我变得更加困惑.我假设乘法必须用一个附加=*,零= 1来替换Monoid [Int].但是f:A => B缺失.如果我遵循乘法我没有发现任何连接到Monoid或函数等.
sealed trait IntMultiplication extends NewType[Int]
trait NewType[X] {
val value: X
override def toString = value.toString
}
Run Code Online (Sandbox Code Playgroud)
有与implicits打交道时一些有用的编译器标志:-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));
Run Code Online (Sandbox Code Playgroud)
现在很清楚了
Monoid.monoid[Int](Semigroup.IntSemigroup, Zero.IntZero)
Run Code Online (Sandbox Code Playgroud)
用于创建Monoid[Int]实例(使用append = +和zero = 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));
Run Code Online (Sandbox Code Playgroud)
在这种情况下Monoid[IntMultiplication](使用append =*和zero = 1)用作隐式参数.
要Monoid为您的类型创建,您需要具有隐式Semigroup和Zero范围
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)
Run Code Online (Sandbox Code Playgroud)
Scalaz 6将类型类实例存储在类型类本身的伴随对象中,因此您需要在那里查找.
在Monoid [T]的情况下,实际的类型类可以分为两部分:Semigroup [T]为我们提供了追加操作(T,T)=> T,Zero [T]为我们提供了一个零函数:()然后,可以通过生活在MonoidLow中的隐式def monoid生成实际的Monoid实例.
对于可折叠,可折叠[List]的类型类存在于可折叠单例内,称为ListFoldable.
我确定你已经解决了,整数范围内的默认monoid是(+,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
两者都触及幺半群.