Spróbuj psychicznie (lub za pomocą edytora tekstu) wypełnienie typów podanych w definicji klasy z typem już używany w danej instancji.
Od:
class Print a where
print :: a -> String
i
data A t = A t
chcemy
instance Print A
więc, podstawiając a
w definicji klasy typu dla A
mówimy jest instnace, otrzymujemy to:
class Print A where
print :: A -> String
Uh-oh. A -> String
nie ma sensu jako typ, ponieważ strzałka typu funkcji przyjmuje typ po lewej stronie, a typ po prawej i podaje typ funkcji. Ale A
nie jest typem, ponieważ zadeklarowałeś A
z data A t
; A t
to typ dla dowolnego typu t
, ale A
jest konstruktorem typu . Może utworzyć typ, jeśli zastosujesz go do typu, ale sama nazwa użytkownika to coś innego. Więc możesz zrobić A t
w instancję Print
, ale nie samą A
.
Dlaczego więc zadziałał instance Functor IO
? Przyjrzyjmy się definicji klasy:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Teraz spróbujmy zastępując IO
dla f
:
class Functor IO where
fmap :: (a -> b) -> IO a -> IO b
na IO
s skończyć stosowane do wpisywania parametrów, więc to wszystko działa. W tym przypadku pojawiłyby się problemy, gdybyśmy próbowali utworzyć konkretny typ, taki jak Int
lub A t
, instancja o numerze Functor
.