Scala PartialFunction 可以是 Monoid 吗?

标签 scala functional-programming scalaz partialfunction monoids

我以为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/

相关文章:

string - 如何在 Scala 中分割给定位置列表的字符串

java - 如何定义方法返回 this 的结构类型

scala - 我们可以在spark.map函数中使用外部map对象吗

Clojure:使用多个参数的函数进行过滤

functional-programming - 用于进度报告的惯用 clojure?

scala - 如何为 cats Free Monad 中使用的 ADT 创建仿函数

scala - 为 Spark 序列化 Scalaz 订单

scala - 使用 -feature 重新运行以获取详细信息

javascript - 在高阶函数中传递附加参数

scalaz - 如何在 2 个 Kleisli Arrows 上使用 `split`