为什么我不能使用这种非参数化类型创建实例?

Jof*_*sey 6 haskell typeclass

为什么这段代码是正确的

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)


And*_*ewC 9

当你说

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是一种构造,只是喜欢IOA有.你能做到的

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.)