/ / Підняття функції, яка приймає неявний параметр за допомогою функтора (Scalaz7) - scala, scalaz, scalaz7

Піднімання функції, яка приймає неявний параметр за допомогою функтора (Scalaz7) - scala, scalaz, scalaz7

Щойно розпочав навчання Scalaz. Ось мій код

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)

Як зняти такі функції?

Відповіді:

0 для відповіді № 1

Ваш метод addXY потребує a 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)