Снятие функции, которая принимает неявный параметр, используя функтор (Scalaz7)
Только начал изучать Скалаз. Вот мой код
trait Monoid[A] {
def mappend(a1: A, a2: A): A
def mzero: A
}
object Monoid {
implicit val IntMonoid: Monoid[Int] = new Monoid[Int] {
def mappend(a1: Int, a2: Int): Int = a1 + a2
def mzero: Int = 0
}
implicit val StringMonoid: Monoid[String] = new Monoid[String] {
def mappend(a1: String, a2: String): String = a1 + a2
def mzero: String = ""
}
}
trait MonoidOp[A] {
val F: Monoid[A]
val value: A
def |+|(a2: A): A = F.mappend(value, a2)
}
object MonoidOp{
implicit def toMonoidOp[A: Monoid](a: A): MonoidOp[A] = new MonoidOp[A]{
val F = implicitly[Monoid[A]]
val value = a
}
}
Я определил функцию (просто ради этого)
def addXY[A: Monoid](x: A, y: A): A = x |+| y
Я хочу поднять его, чтобы он мог использоваться с использованием таких контейнеров, как Option, List и т. Д. Но когда я делаю это
def addXYOptioned = Functor[Option].lift(addXY)
Это говорит error: could not find implicit value for evidence parameter of type scalaz.Monoid[A]
def addOptioned = Functor[Option].lift(addXY)
Как поднять такие функции?
1 ответ
Ваш метод addXY
нужен Monoid[A]
но нет Monoid[A]
по объему при использовании в addXYOptioned
так что вам также нужно добавить Monoid
ограничение к addXYOptioned
,
Следующая проблема заключается в том, что Functor.lift
только поднимает функцию A => B
, но мы можем использовать Apply.lift2
поднять функцию (A, B) => C
,
С использованием Monoid
от самого Скалаза:
import scalaz._, Scalaz._
def addXY[A: Monoid](x: A, y: A): A = x |+| y
def addXYOptioned[A: Monoid] = Apply[Option].lift2(addXY[A] _)
Мы могли бы обобщить addXYOptioned
чтобы можно было поднять addXY
в конструктор любого типа с Apply
пример:
def addXYApply[F[_]: Apply, A: Monoid] = Apply[F].lift2(addXY[A] _)
addXYApply[List, Int].apply(List(1,2), List(3,4))
// List[Int] = List(4, 5, 5, 6)
addXYApply[Option, Int].apply(1.some, 2.some)
// Option[Int] = Some(3)