Brillemos una luz diferente sobre esto.
PartialFunction[A, B]
es isomorfo a A => Option[B]
. (En realidad, para poder comprobar si se ha definido para un determinado A
sin desencadenar la evaluación de la B
, se necesitaría A => LazyOption[B]
)
Así que si podemos encontrar un Monoid[A => Option[B]]
hemos probado su afirmación.
Dado Monoid[Z]
, podemos formar Monoid[A => Z]
de la siguiente manera:
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))
}
Por lo tanto, lo que Monoid (s) tenemos si usamos como nuestro Option[B]
Z
? Scalaz proporciona tres. La instancia principal requiere un 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
}
}
}
El uso de este:
scala> Monoid[Option[Int]].append(Some(1), Some(2))
res9: Option[Int] = Some(3)
Pero eso no es la única manera de combinar dos opciones. En lugar de anexar el contenido de las dos opciones en el caso de que ambas sean Some
, podríamos simplemente elegir la primera o la última de las dos. Dos activan esto, creamos un tipo distinto con truco llamado Tipos Etiquetados. Esto es similar en espíritu a Haskell's newtype
.
scala> import Tags._
import Tags._
scala> Monoid[Option[Int] @@ First].append(Tag(Some(1)), Tag(Some(2)))
res10: [email protected]@[Option[Int],scalaz.Tags.First] = Some(1)
scala> Monoid[Option[Int] @@ Last].append(Tag(Some(1)), Tag(Some(2)))
res11: [email protected]@[Option[Int],scalaz.Tags.Last] = Some(2)
Option[A] @@ First
, anexa a través de su Monoid
, utiliza los mismos orElse
semántica que tu ejemplo.
lo tanto, poner todo esto junto:
scala> Monoid[A => Option[B] @@ First]
res12: scalaz.Monoid[A => [email protected]@[Option[B],scalaz.Tags.First]] =
[email protected]
Asumo que son conscientes de que 'Function1' es un monoide bajo composición? –
@dcsobral 'Function1 [A, A]', aka 'Endo [A]', es. – retronym