簡體   English   中英

| + | 是一個半群,為什么它需要一個monoid隱式解析

[英]|+| is a semigroup, why it needs a monoid implicit resolution

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已經存在List[A]Semigroup 您已經為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提供的實例保持在范圍之外,但請不要! - 對於其他用戶而言可能非常混亂,並且違反了使用類型類一些基本良好原則 相反,您可以為List[Staff]編寫一個包裝器(一個簡單的案例類),然后為該類型提供一個實例。


為了完整起見,值得注意的是,與版本Monoid編譯,因為Monoid比更具體的Semigroup (見第6.26.3 語言規范的,在這里適用的規則,但被警告,他們是那種亂七八糟)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM