Hãy thử tinh thần (hoặc với một trình soạn thảo văn bản) điền vào các loại được đưa ra trong định nghĩa lớp với loại mà bạn đã sử dụng trong ví dụ.
Từ:
class Print a where
print :: a -> String
và
data A t = A t
chúng tôi muốn
instance Print A
Vì vậy, thay a
trong định nghĩa kiểu lớp cho A
chúng tôi đang nói là một instnace, chúng tôi nhận được điều này:
class Print A where
print :: A -> String
Uh-oh. A -> String
không có ý nghĩa như một loại, vì mũi tên kiểu hàm có một loại ở bên trái và một loại ở bên phải, và cung cấp cho bạn loại hàm. Nhưng A
không phải là một loại, vì bạn đã khai báo A
với data A t
; A t
là loại cho bất kỳ loại nào t
, nhưng A
là một phương thức khởi tạo loại . Nó có thể tạo ra một loại nếu bạn áp dụng nó cho một loại, nhưng chính bản thân nó là một cái gì đó khác. Vì vậy, bạn có thể tạo A t
thành một phiên bản Print
, nhưng không phải là A
.
Vậy tại sao instance Functor IO
hoạt động? Cho phép xem xét các định nghĩa lớp:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Bây giờ cho phép thử thay IO
cho f
:
class Functor IO where
fmap :: (a -> b) -> IO a -> IO b
Các IO
s cuối lên áp dụng cho gõ thông số, vì vậy nó tất cả các công trình ra. Ở đây, chúng tôi sẽ gặp sự cố nếu chúng tôi cố gắng tạo loại bê tông như Int
hoặc A t
một phiên bản của Functor
.