Jest tu kilka dużych problemów.
Po pierwsze, instancja Monad
musi mieć kind* -> *
. Oznacza to, że potrzebna jest co najmniej jedna zmienna typu , w której Twój Something
nie ma żadnych. Dla porównania:
-- kind * -> *
Maybe
IO
Either String
-- kind *
Maybe Int
IO()
Either String Double
Zobacz, jak każdy z Maybe
, IO
i Either String
potrzebują parametr typu, zanim będzie można z nich korzystać? Z Something
, nie ma miejsca dla parametru Typ wypełnić Więc trzeba zmienić definicję.
data Something a = Something a
Drugim wielkim problemem jest to, że w przypadku >>=
Monad jest źle. Zwykle nie można używać do-notacji, ponieważ to po prostu wywołuje funkcje Monad
funkcji return
i >>=
. Musisz więc napisać to bez żadnych funkcji monady, albo do-notacji, albo wywołując >>=
lub return
.
instance Monad Something where
return a = Something a --Wraps a in 'Something'
(Something m) >>= f = f m --unwraps m and applies it to f
Definicja >>=
jest prostsza niż oczekiwano. Rozpakowanie m
jest łatwe, ponieważ wystarczy dopasować do wzoru na konstruktorze Something
. Również f :: a -> m b
, więc nie musisz się martwić o jego zawijanie, ponieważ f
robi to za ciebie.
Chociaż nie ma sposobu, aby rozpakować monady w ogólnym, bardzo wiele specyficzne monady można odwinąć.
Należy pamiętać, że nie ma nic niewłaściwego syntaktycznie w używaniu notacji-do-notacji lub >>=
w deklaracji monad. Problem polega na tym, że >>=
jest zdefiniowany rekursywnie, więc program próbuje przejść do niekończącej się pętli.
(nb Something
zdefiniowany tutaj jest Identity monad)
Na swoim trzecim pytaniu, tak funkcja return
zdefiniowane w instancji Monad to taka, która zostanie wywołana. Klasy typów są wywoływane według typu, a ponieważ określony typ musi być Something b
, kompilator automatycznie użyje instancji Monad dla Something
. (Myślę, że oznaczało to, że ostatnia linia to doMagicTo var
).
To jest świetne. Wszystkie te odpowiedzi są tak dobre. Czuję się zmuszony zauważyć, że społeczność Haskell była jak dotąd najbardziej pomocna i dokładna, z jakimi się zetknąłem. Na zdrowie. – providence