Podaje potrzebne typy.
To jasne od znaczenia w instance
definicji, że próbujesz określić
returnMaybeT :: Monad m => a -> MaybeT m a
returnMaybeT x = MaybeT (return (return x))
Od MaybeT :: m (Maybe a) -> MaybeT a
(rozumianej jako funkcja) Wiemy, że wewnętrzna stos return
s musi mieć typ
return (return x) :: Monad m => a -> m (Maybe a)
teraz wiemy, że return
jest polimorficzny funkcja, która ma typ jak
return :: a -> n a
dla dowolneMonad
n
. W przypadku tego pierwszego return
, ograniczenie Monad m =>
mówi nam, że m
jest i dlatego możemy użyć jego definicji zwrotu. Pozwala nam to uzyskać przez całą drogę w dół do wewnętrznej return
return x :: a -> Maybe a
a ponieważ wiemy, że Maybe
ma instancję Monad
możemy użyć return
od tego.
Ostatecznie wszystko kompilator musi zrobić, to zredukować jego droga w dół ekspresji próby określenia rodzajów potrzebnych na każdym return
. Po określeniu wymaganego typu musi sprawdzić, czy zna instancję Monad
dla tego typu. Jest to proste dla Maybe
, ponieważ jest konkretne, ale nieco trudniejsze do zobaczenia dla m
, ponieważ jest to tylko zmienna.
Powodem m
prace dlatego mamy ograniczone zmienną pewnością niektóre typ który instancję Monad
.
Nie powinien być pierwszym zwrotem z ostatniej linii albo typu 'Może a -> m (Może a)' lub bardziej ogólnego 'b -> m b' z' b ~ Może a'? – Laar
@Laar Technicznie tak, ale łatwiej jest (i moralnie równoważne) traktować to w ten sposób. – jozefg