2012-11-25 8 views
5

Il caso generale di monad è espresso in Java 6? Notare le parole "caso generale" — potrebbe essere possibile che il caso generale di monade non sia esprimibile, sebbene molti casi particolari di monade (cioè molte monadi specifiche) siano espressi.Il caso generale di monad è espresso in java 6?

Il problema qui è (mancanza) Higher-kinded generics in Java; tuttavia, ho visto che il codice Haskell di esempio è stato effettivamente portato su Java utilizzando l'approccio come https://stackoverflow.com/a/877036/1123502 (ovvero, public class Fix<F extends Fix<F>>).

Ovviamente, le implementazioni non di tipo sicuro (come l'utilizzo di Object e downcasts) non sono interessanti.

Aggiornamento: ci sono 2 definizioni di monade comuni: join-fmap e bind-return. Sebbene siano (matematicamente) equivalenti, potrebbero non essere equivalenti nel senso che una definizione è espressa in Java, mentre altri non lo sono (tuttavia, mi sembra, che la non equivalenza sia improbabile). Quindi la mia domanda riguarda entrambe le definizioni.

La linea di fondo: qualcuno ha superato tutti gli ostacoli e ha scritto monade "general case" in Java 6? Oppure, in alternativa, indica un foglio o un post completo sul blog o spiega dettagliatamente perché non è possibile.

+2

Vedere anche [* Monads in Java *] (http://logicaltypes.blogspot.com/2011/09/monads-in-java.html). – trashgod

+2

@trashgod Nota che in quell'implementazione il tipo restituito di 'bind' è' Monad '- non' M ', che non sarebbe possibile in Java. Di conseguenza, se hai una classe List che eredita da Monad, non c'è alcuna garanzia che chiamando 'bind' su tale lista produrrà un altro elenco, quindi non sarebbe legale scrivere qualcosa come' MonadicList stringhe = myMonadicList.bind (...) 'senza un cast. ... – sepp2k

+1

... Quindi la classe astratta fornita in quell'articolo non è un'implementazione completamente corretta del concetto di monade (anche se probabilmente è il più vicino a correggere come si può ottenere in Java). – sepp2k

risposta

5

Non senza sporchi trucchetti. Come già notato, Java non supporta il polimorfismo a livello di tipo (a.k.a. "tipi di tipi più elevati" in Scala).

Ecco un modo: Dire che si desidera implementare un funtore. Si desidera scrivere Functor<F<A>>, dove F è ad esempio a List o Maybe, ma questo non funziona. Ma puoi avere una "classe base" Base<X,Y> per le cose più generose. X deve essere un "testimone" per la tua vera classe come List. Y è il solito parametro generico. Ora il vostro functor diventa Functor<Base<F,A>>, ma tutte le classi che vogliono essere utilizzato con questo, hanno bisogno di implementare Base<X,Y>:

class List<A> implements Base<List.Witness,A> { 
    public class Witness{} 
    ... 
} 

public interface Functor<F> { 
    public <A, B> Base<F, B> map(F1<A, B> fn, Base<F, A> nestedA); 
} 

public class ListFunctor implements Functor<List.Witness> { 
    public <A, B> Base<List.Witness, B> map(F1<A, B> fn, Base<List.Witness, A> nestedA) { 
     ... 
    } 
} 

Naturalmente il prezzo da pagare è che si ottiene indietro un Base<List.Witness,B>, non un List<B>. Questo potrebbe andar bene se rimani in quel dominio di livello superiore e, naturalmente, puoi avere funzioni di conversione per comodità, ma non è ancora molto bello.

Per un'implementazione, vedere il mio progetto non troppo serio highJ. Nota che sto lavorando ad una versione completamente riscritta e leggermente più comoda più vicina all'esempio sopra.

Per codice serio, è consigliabile scrivere tali elementi in Scala (o utilizzare Scalaz).

Problemi correlati