2016-07-11 4 views
0

Gerade erst begonnen, Scalaz zu lernen. Hier ist mein CodeAnheben einer Funktion, die implizite Parameter mit Funktor nimmt (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 
    } 
} 

ich eine Funktion definiert haben (nur im Interesse der es)

def addXY[A: Monoid](x: A, y: A): A = x |+| y 

ich möchte es heben, so dass es Container wie Option verwendet werden könnten, verwenden, List, etc Aber., wenn ich dies tun

def addXYOptioned = Functor[Option].lift(addXY) 

Es sagt error: could not find implicit value for evidence parameter of type scalaz.Monoid[A] def addOptioned = Functor[Option].lift(addXY)

Wie so viel Spaß heben ctions?

+0

Zwei Dinge: (1) Ihre Funktion nimmt zwei Argumente anstelle von einem (streng genommen hat sie zwei Argumentlisten, da die Kontextgrenze ein impliziter Parameter ist). (2) Ich glaube nicht, dass es möglich ist, Kontextgrenzen mit Funktoren zu verwenden, siehe auch http://stackoverflow.com/questions/10849142/how-can-scalaz-functor-be-given-a-higher-kinded- Typ-mit-einem-Kontext gebunden. – devkat

Antwort

0

Ihre Methode addXY eine Monoid[A] braucht aber es gibt keine Monoid[A] in Umfang, wenn sie in addXYOptioned verwendet, so müssen Sie auch die Monoid Einschränkung addXYOptioned hinzuzufügen.

Das nächste Problem ist, dass Functor.lift nur eine Funktion A => B hebt, aber wir können Apply.lift2 verwenden, um eine Funktion (A, B) => C zu heben.

Mit der Monoid von Scalaz selbst:

import scalaz._, Scalaz._ 

def addXY[A: Monoid](x: A, y: A): A = x |+| y 

def addXYOptioned[A: Monoid] = Apply[Option].lift2(addXY[A] _) 

Wir konnten addXYOptioned verallgemeinern, um es möglich addXY in jede Art Konstruktor mit einer Apply Instanz zu heben:

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) 
Verwandte Themen