2010-01-02 13 views
23

(Come) è possibile rappresentare monad in Scala in modo generico (come la classe di caratteri Monad in Haskell)? È in qualche modo possibile definire un trait Monad per questo scopo?Monade trait in Scala

risposta

40

si potrebbe provare qualcosa di simile:

trait Monad[+M[_]] { 
    def unit[A](a: A): M[A] 
    def bind[A, B](m: M[A])(f: A => M[B]): M[B] 
} 

// probably only works in Scala 2.8 
implicit def monadicSyntax[M[_], A](m: M[A])(implicit tc: Monad[M]) = new { 
    private val bind = tc.bind(m) _ 

    def map[B](f: A => B) = bind(f compose tc.unit) 

    def flatMap[B](f: A => M[B]) = bind(f) 
} 

implicit object MonadicOption extends Monad[Option] { 
    def unit[A](a: A) = Some(a) 

    def bind[A, B](opt: Option[A])(f: A => Option[B]) = opt flatMap f 
} 

si sarebbe naturalmente definire gli oggetti impliciti simili per qualsiasi altro monade il tuo cuore desidera. In termini Haskell, puoi pensare a Monad come la classe di caratteri e MonadicOption come un'istanza particolare di quella classe di tipi. La conversione implicita di monadicSyntax dimostra semplicemente come questa classe di caratteri possa essere utilizzata per consentire l'uso delle for -screazioni di Scala con qualsiasi cosa che soddisfi la classe di caratteri Monad.

In generale, la maggior parte delle cose nella libreria standard di Scala che implementano flatMap sono monade. Scala non definisce una generica classe di caratteri Monad (anche se sarebbe molto utile). Invece, si basa su un trucco sintattico del parser per consentire l'uso di for -comprehensions con qualsiasi cosa che implementa i metodi appropriati. Nello specifico, tali metodi sono map, flatMap e filter (o foreach e filter per la forma imperativa).

+0

Grazie, questo era esattamente quello che stavo cercando. Volevo solo definire generiche funzioni di monad e trasformatori in un modo generale ... – Dario

+3

In realtà non lo userai per qualcosa di reale, vero? :-) Scherzi a parte, ho lavorato con Scala per un po ', e ho scoperto che molti casi in cui Haskell usa la classe di caratteri Monad non si presentano in Scala a causa di tratti e sottotitoli. Il typeclass di cui sopra, seppure fico, non sarebbe certamente il modo idiomatico per risolvere problemi in Scala. –

+1

Ma loro escono. Arrivano tutto il tempo. Un paio di volte al giorno, voglio 'liftA2' o' sequenceA'. Certo, questi richiedono solo Applicativo piuttosto che Monad, ma comunque, se questi non vengono visualizzati nella tua programmazione, devi scrivere qualcosa di molto semplice. – Apocalisp

14

È possibile che il progetto scalaz sia interessante; ha anche molte altre cose (funzionali) oltre a un'implementazione delle monadi.

2

Scala raggiunge un potere simile alle classi di tipi di Haskell tramite l'uso di parametri impliciti, in particolare limiti di vista e limiti di contesto. Puoi vedere queste cose in uso in particolare su Scala 2.8, con tratti come Ordering e Numeric.

Detto questo, guarda il progetto Scalaz. Ha monadi, funtori, frecce ... l'intero shebang.

4

http://www.codecommit.com/blog/ruby/monads-are-not-metaphors

Ecco un articolo utile e piuttosto lunga circa il modello Monade e la sua attuazione in Scala da Daniel, che ha scritto il accettato rispondi a questa domanda

(Per coloro che inciampano su questa "antica" questione attraverso le vie mistiche del StackOverflow sito-ricerca.)