斯卡拉 – | |是一个半群,为什么它需要一个monoid隐式解析
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) 如果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) //// } 提前谢谢了 编辑 接下来是@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 是因为在Scalaz中,没有指定像Foo这样的方法中指定的类型. 解决方法
问题是,对于任何A,已经有一个Semigroup for List [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]] ^ 您可以跳过一些箍并尝试将Scalaz提供的实例保持在范围之外,但请不要! – 对于其他用户而言可能非常混乱并且违反了some basic good principles for working with type classes.相反,您可以为List [Staff]编写一个包装器](一个简单的案例类),然后提供该类型的实例. 为了完整起见,值得注意的是Monoid编译的版本因为Monoid比Semigroup更具体(参见language specification的6.26.3节,适用于此处适用的规则,但要注意它们有点混乱) . (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |