我以为PartialFunction可以 Monoid .我的思维过程正确吗?
例如,
import scalaz._
import scala.{PartialFunction => -->}
implicit def partialFunctionSemigroup[A,B]:Semigroup[A-->B] = new Semigroup[A-->B]{
def append(s1: A-->B, s2: => A-->B): A-->B = s1.orElse(s2)
}
implicit def partialFunctionZero[A,B]:Zero[A-->B] = new Zero[A-->B]{
val zero = new (A-->B){
def isDefinedAt(a:A) = false
def apply(a:A) = sys.error("error")
}
}
但当前版本 Scalaz(6.0.4) 不包括在内。有什么不包括在内的原因吗?
最佳答案
让我们用不同的眼光来看待这个问题。PartialFunction[A, B]
同构于 A => Option[B]
. (实际上,为了能够在不触发对 A
的评估的情况下检查它是否是为给定的 B
定义的,您需要 A => LazyOption[B]
)
所以如果我们能找到一个 Monoid[A => Option[B]]
我们已经证明了你的主张。
给定 Monoid[Z]
, 我们可以形成 Monoid[A => Z]
如下:
implicit def readerMonoid[Z: Monoid] = new Monoid[A => Z] {
def zero = (a: A) => Monoid[Z].zero
def append(f1: A => Z, f2: => A => Z) = (a: A) => Monoid[Z].append(f1(a), f2(a))
}
那么,如果我们使用
Option[B]
,我们有什么 Monoid(s)?作为我们的 Z
? Scalaz 提供了三个。主实例需要 Semigroup[B]
.implicit def optionMonoid[B: Semigroup] = new Monoid[Option[B]] {
def zero = None
def append(o1: Option[B], o2: => Option[B]) = o1 match {
case Some(b1) => o2 match {
case Some(b2) => Some(Semigroup[B].append(b1, b2)))
case None => Some(b1)
case None => o2 match {
case Some(b2) => Some(b2)
case None => None
}
}
}
使用这个:
scala> Monoid[Option[Int]].append(Some(1), Some(2))
res9: Option[Int] = Some(3)
但这并不是结合两个选项的唯一方法。如果这两个选项都是
Some
,则不会附加这两个选项的内容。 ,我们可以简单地选择两个中的第一个或最后一个。两个触发这个,我们用称为标记类型的技巧创建了一个不同的类型。这在精神上类似于 Haskell 的 newtype
.scala> import Tags._
import Tags._
scala> Monoid[Option[Int] @@ First].append(Tag(Some(1)), Tag(Some(2)))
res10: scalaz.package.@@[Option[Int],scalaz.Tags.First] = Some(1)
scala> Monoid[Option[Int] @@ Last].append(Tag(Some(1)), Tag(Some(2)))
res11: scalaz.package.@@[Option[Int],scalaz.Tags.Last] = Some(2)
Option[A] @@ First
,通过它附加 Monoid
, 使用相同的 orElse
语义作为你的例子。所以,把这一切放在一起:
scala> Monoid[A => Option[B] @@ First]
res12: scalaz.Monoid[A => scalaz.package.@@[Option[B],scalaz.Tags.First]] =
scalaz.std.FunctionInstances0$$anon$13@7e71732c
关于Scala PartialFunction 可以是 Monoid 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9067904/