これに別の光を当てましょう。
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