Xia*_*ong 9 functional-programming scala scalaz scalaz7
Semigroup的目的是确保关联性和闭合性monoid的目标是基于Semigroup并提供额外的身份.当我使用| + | semigroup appender,为什么我定义了隐式monoid而不是隐式半群
这是我使用reduceLeft的代码,它不需要初始值
val result1 = List(Staff("John", 36), Staff("Andrew", 30))
val result2 = List(Staff("John", 40), Staff("Danny", 30))
val result3 = List(Staff("Andrew", 30))
val result4: List[Staff] = List()
implicit val staffListSemigroup = new Monoid[List[Staff]] {
override def zero: List[Staff] = Nil
override def append(f1: List[Staff], f2: => List[Staff]): List[Staff] = {
val mapSemigroup = f1.map(t => (t.name, t.numberOfTasks)).toMap |+| f2.map(t => (t.name, t.numberOfTasks)).toMap
mapSemigroup.map(t => Staff(t._1, t._2)).toList
}
}
val result = List(result1, result2, result3, result4).reduceLeft(_ |+| _)
assert(result.size == 3)
Run Code Online (Sandbox Code Playgroud)
如果staffListSemigroup是Semigroup [List [Staff]],则编译错误为值| + | 不是List [SemigroupSpec.this.Staff]的成员
另外,| + |的定义 在半群里面
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)
////
}
Run Code Online (Sandbox Code Playgroud)
提前谢谢了
编辑
接下来是@Travis回答,我不认为这是正确的.对于隐含值,特定值将始终覆盖通用值.这是我刚才写的代码示例:
case class Foo(i : Int, s : String)
class Test[T] {
def print = "print test"
}
implicit val test = new Test[Any]
implicit val testMoreSpecific = new Test[Foo] {
override def print = "print Foo"
}
def doStuff[A](implicit test: Test[A]) = {
test.print
}
doStuff[Foo] //it successfully print out print Foo
doStuff //compilation error, ambiguous implicit value found
Run Code Online (Sandbox Code Playgroud)
是因为在Scalaz中,没有指定像Foo这样的方法中指定的类型.
问题是,有一个已经Semigroup为List[A]任何A.您已经定义了一个更具体的实例List[Staff],这会导致模糊,正如您可以通过询问实例看到的那样:
scala> Semigroup[List[Staff]]
<console>:17: error: ambiguous implicit values:
both method listMonoid in trait ListInstances of type [A]=> scalaz.Monoid[List[A]]
and value staffListSemigroup of type => scalaz.Semigroup[List[Staff]]
match expected type scalaz.Semigroup[List[Staff]]
Semigroup[List[Staff]]
^
Run Code Online (Sandbox Code Playgroud)
您可以跳过一些环节并尝试将Scalaz提供的实例保持在范围之外,但请不要! - 对于其他用户而言可能非常混乱,并且违反了使用类型类的一些基本良好原则.相反,您可以编写一个包装器List[Staff](一个简单的案例类),然后为该类型提供一个实例.
为了完整起见,值得注意的是,带有Monoid编译的版本因为Monoid更具体Semigroup(请参阅适用于此处的规则的语言规范的第6.26.3节,但要注意它们有点混乱).