2012-11-25 7 views
5

Czy ogólny przypadek monady można wyrazić w Javie 6? Zauważ, że słowa "ogólny przypadek" — może być możliwe, że ogólny przypadek monady nie jest możliwy do wyklarowania, chociaż wiele szczególnych przypadków monady (to jest wielu specyficznych monad) jest możliwych do wyrażenia.Czy ogólny przypadek monady można wyrazić w języku Java 6?

Problemem tutaj jest (brak) Higher-kinded generics in Java; jednak widziałem, że przykładowy kod Haskella był naprawdę przeniesiony na Javę przy użyciu podejścia takiego jak https://stackoverflow.com/a/877036/1123502 (czyli public class Fix<F extends Fix<F>>).

Oczywiście implementacje, które nie są typem bezpiecznym (takie jak używanie obiektów i downcastów), nie są interesujące.

Aktualizacja: Istnieją 2 wspólne definicje monad: join-fmap i bind-return. Chociaż są one (matematycznie) równoważne, mogą nie być równoważne w tym sensie, że jedna definicja jest możliwa do wyrażenia w Javie, podczas gdy inne nie (jednak wydaje mi się, że niewiarygodność jest mało prawdopodobna). Moje pytanie dotyczy więc obu definicji.

Najważniejsze: czy ktoś pokonywał wszystkie przeszkody i napisał monadę "general case" w Javie 6? Możesz też wskazać artykuł lub dokładny wpis na blogu lub dokładnie wyjaśnić, dlaczego nie jest to możliwe.

+2

Zobacz także [* Monady w Javie *] (http://logicaltypes.blogspot.com/2011/09/monads-in-java.html). – trashgod

+2

@trashgod Zwróć uwagę, że w tej implementacji typem powrotu 'bind' jest' Monad '- a nie' M ', co nie byłoby możliwe w Javie. W związku z tym, jeśli masz klasę List, która dziedziczy po Monadzie, nie ma gwarancji, że wywołanie 'bind' na takiej liście spowoduje utworzenie kolejnej listy, więc nie byłoby zgodne z prawem napisanie czegoś takiego jak' MonadicList stringi = myMonadicList.bind (...) "bez obsady. ... – sepp2k

+1

... Zatem klasa abstrakcyjna podana w tym artykule nie jest całkowicie poprawną implementacją koncepcji monad (choć prawdopodobnie jest tak bliska poprawności, jak w Javie). – sepp2k

Odpowiedz

5

Nie bez zabrudzonych sztuczek odlewniczych. Jak już zauważyłeś, Java nie obsługuje polimorfizmu na poziomie typu (a.k.a. "typy wyższego rodzaju" w Scala land).

Oto jeden sposób: Załóżmy, że chcesz zaimplementować funktora. Chcesz napisać: Functor<F<A>>, gdzie np. F a List lub Maybe, ale to nie działa. Ale możesz mieć "klasę podstawową" Base<X,Y> dla rzeczy o wyższych wymaganiach. X musi być "świadkiem" dla twojej prawdziwej klasy, takiej jak List. Y jest zwykłym parametrem generycznym. Teraz twój funktor staje Functor<Base<F,A>>, ale wszystkie klasy, które chcą być używane z tym należy wdrożyć 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) { 
     ... 
    } 
} 

Oczywiście cena za to, że wrócisz do Base<List.Witness,B>, a nie List<B>. Może to być dobre, jeśli pozostaniesz w domenie wyższej kategorii i oczywiście możesz mieć funkcje konwersji dla wygody, ale nadal nie jest to zbyt miłe.

W celu realizacji zobacz mój niezbyt poważny projekt highJ. Zauważ, że pracuję nad całkowicie przepisaną i nieco bardziej wygodną wersją bliżej przykładu powyżej.

Dla poważnego kodu, rozważ napisanie takich rzeczy w Scali (lub użyj Scalaz).

Powiązane problemy