为什么这段代码是正确的
instance Functor IO where -- note that IO isn't parametrized, and it's correct
fmap f action = do
result <- action
return (f result)
Run Code Online (Sandbox Code Playgroud)
但是下面的代码有编译错误?
class Print a where
print :: a -> String
data A t = A t
instance Print A where -- error: expecting one more argument to `A'
print a = "abc"
Run Code Online (Sandbox Code Playgroud)
ham*_*mar 11
这是因为种类不匹配.常规类型有类型*,而类型构造函数如A或者IO有类* -> *,表示它们需要一个类型参数才能返回一个类型.
在Print类的定义中,编译器推断自从a用作普通类型时,它必须具有类型*.但是,Functor适用于类型构造函数* -> *:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
这里,f不是用作普通类型,而是用作类型构造函数,所以推断类型是* -> *.您可以使用:kindGHCi中的命令验证这一点:
> :kind Print
Print :: * -> Constraint
> :kind Functor
Functor :: (* -> *) -> Constraint
Run Code Online (Sandbox Code Playgroud)
当你说
class Print a where
print' :: a -> String
Run Code Online (Sandbox Code Playgroud)
你确定a必须是一个类型,但是当你说
data A t = A t
Run Code Online (Sandbox Code Playgroud)
你创建A一个类型构造函数 - A不是一个类型,但是A Int,例如.A是类型的一种函数,但aPrint类中的函数必须是类型值,而不是类型函数.
你可以做到
instance Print (A Int) where
print' a = "abc"
Run Code Online (Sandbox Code Playgroud)
这是可以的,IO因为Functor类要求一个类型构造函数.
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
你可以看到,因为f a是一个类型,f是一种构造,只是喜欢IO和A有.你能做到的
instance Functor A where -- OK, A is a constructor, Functor needs one
fmap f (A x) = A (f x)
Run Code Online (Sandbox Code Playgroud)
你将无法做到
instance Eq IO where -- not OK - IO is a constructor and Eq needs a type
(==) = error "this code won't compile"
Run Code Online (Sandbox Code Playgroud)
(我用过print'而不是print为了避免与标准函数发生冲突print.)