2013-05-07 30 views
15

Mi sembra che Scalaz 'NonEmptyList abbia un'istanza monad, quindi un trasformatore monad per esso (un po' simile a ListT) dovrebbe essere possibile. È corretto?Monad transformer per NonEmptyList?

Se è così, c'è uno là fuori? (Non riuscivo a trovarne uno in Scalaz 7.)

In caso contrario, ad esempio un trasformatore monad per esso sarebbe impossibile o non ha alcun senso, sarei grato per qualsiasi spiegazione aggiuntiva sul perché no.

+0

Posso suggerire di provare a crearne uno e a contribuire! –

+0

Questo era assolutamente il mio piano. = ^.^= Ma volevo evitare di provare a implementare qualcosa che non può funzionare per principio. NEL sembra un po '"ampiamente" usato, quindi ho attribuito l'inesistenza di un trasformatore monad per ciò che non caccio (ancora) invece di (semplicemente) a "nessuno ha trovato il tempo di farlo ancora". –

+1

Il modo migliore è spesso quello di provare come di consueto se è impossibile sarà subito ovvio. :) –

risposta

4

È certamente possibile, come si può dimostrare che ogni monade che dispone di un'istanza Traverse può essere trasformato in un trasformatore monad:

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)) 
    } 
} 

Questo non è chiaramente la forma più conveniente da lavorare, ma spettacoli che è, infatti, possibile. Tom Switzer sta attualmente lavorando all'aggiunta di un trasformatore monod TraverseT molto più utile e generico a scalaz. È possibile see his progress on GitHub