14

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) には含まれていません。含まれていない理由はありますか?

4

3 に答える 3

28

これに別の光を当てましょう。

PartialFunction[A, B]に同型A => Option[B]です。A(実際には、の評価をトリガーせずに、特定の に対して定義されているかどうかを確認できるようにするにはB、 が必要ですA => LazyOption[B])

したがって、 a を見つけることができれば、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]では、として使用すると、どのモノイドが得られるZでしょうか? Scalaz は 3 つ提供します。プライマリ インスタンスには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)

しかし、2 つのオプションを組み合わせる方法はこれだけではありません。2 つのオプションが both である場合にその内容を追加するのではなく、Some単純に 2 つの最初または最後を選択することができます。2 つがこれをトリガーします。タグ付きタイプと呼ばれるトリックを使用して、個別のタイプを作成します。これは 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
于 2012-01-30T23:03:00.753 に答える
2

いいえ、これは良さそうで、(非可換) モノイドの両方の要件を満たしています。興味深いアイデアです。サポートしようとしているユースケースは何ですか?

于 2012-01-30T18:52:52.930 に答える
0

あなたのゼロは確かに単位元の公理に違反していますが、単位(部分)関数は大丈夫だと思います。

あなたの追加もモノイドの法則を満たしていませんが、orElseの代わりにandThen 構成)を呼び出すことができます。ただし、これはA==Bの場合にのみ機能します。

implicit def partialFunctionSemigroup[A]: Semigroup[A --> A] = new Semigroup[A --> A] {
  def append(s1: A --> A, s2: => A --> A): A-->A = s1 andThen s2
}

implicit def partialFunctionZero[A]: Zero[A --> A] = new Zero[A --> A] {
  val zero = new (A --> A) {
    def isDefinedAt(a:A) = true
    def apply(a:A) = a
  }
}
于 2012-01-30T19:08:14.553 に答える