2013-05-07 6 views
15

Es scheint mir, dass Scalaz 'NonEmptyList eine Monad-Instanz hat, also sollte ein Monade-Transformer dafür (ein bisschen ähnlich wie ListT) möglich sein. Ist das korrekt?Monad Transformator für NonEmptyList?

Wenn ja, gibt es einen da draußen? (Ich konnte einen in Scalaz 7 selbst nicht finden.) Wenn nicht, d. H. Ein Monadetransformator wäre unmöglich oder würde keinen Sinn ergeben, wäre ich dankbar für jede zusätzliche Erklärung, warum nicht.

+0

Ich kann den Vorschlag machen, dass Sie versuchen sollten, eine zu erstellen und dazu beitragen! –

+0

Das war absolut mein Plan. = ^.^= Aber ich wollte vermeiden, etwas zu implementieren, das prinzipiell nicht funktioniert. NEL scheint irgendwie "weit verbreitet" zu sein, daher schrieb ich die Nichtexistenz eines Monade-Transformators dafür etwas zu, was ich (noch) nicht (einfach) verstehe, "niemand hat die Zeit dafür gefunden". –

+1

Der beste Weg ist oft zu versuchen, wenn es unmöglich ist, wird es sofort offensichtlich sein. :) –

Antwort

4

Es ist sicherlich möglich, da es, dass jede Monade gezeigt werden kann, die eine Traverse Instanz hat in einen Monade Transformator erfolgen:

import scalaz._ 
import Scalaz._ 

object MonadT { 
    implicit def monadTransformerFromTraverse[M[_]: Monad, N[_]: Monad: Traverse]: Monad[({type MN[A]=M[N[A]]})#MN] = new Monad[({type MN[A]=M[N[A]]})#MN] { 
    def point[A](a: => A): M[N[A]] = a.point[N].point[M] 
    def bind[A,B](fa: M[N[A]])(f: A=>M[N[B]]) : M[N[B]] = { 
     val M = implicitly[Monad[M]] 
     val NT = implicitly[Traverse[N]] 
     val N = implicitly[Monad[N]] 

     M.map(M.join(M.map(M.map(fa)(N.map(_)(f)))(NT.sequence(_))))(N.join) 
//      |- => M[N[M[N[B]]]] -| 
//     |-  => M[M[N[N[B]]]]     -| 
//   |-    => M[N[N[B]]]      -| 
// |-     => M[N[B]]         -| 


    } 
    } 

    def main(argv: Array[String]) { 
    val x: Option[NonEmptyList[Int]] = Some(NonEmptyList(1)) 
    val f: Int => Option[NonEmptyList[Int]] = { x: Int => Some(NonEmptyList(x+1)) } 

    val MT = monadTransformerFromTraverse[Option, NonEmptyList] 
    println(MT.bind(x)(f)) // Some(NonEmptyList(2)) 
    } 
} 

Dies ist eindeutig nicht die bequemste Form zu arbeiten, sondern zeigt dass es tatsächlich möglich ist. Tom Switzer arbeitet derzeit daran, Scalaz einen viel nützlicheren und allgemeineren TraverseT-Monade-Transformer hinzuzufügen. Sie können see his progress on GitHub