6

为什么这段代码是正确的

instance Functor IO where -- note that IO isn't parametrized, and it's correct
    fmap f action = do
        result <- action
        return (f result)

但是下面的代码有编译错误?

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"
4

3 回答 3

11

这是因为种类不匹配。常规类型有 kind *,而类型构造函数如AorIO有 kind * -> *,表明它们需要一个类型参数才能返回一个类型。

Print类的定义中,编译器推断由于a用作普通类型,因此它必须具有 kind *。但是,Functor适用于 kind 的类型构造函数* -> *

class Functor f where
  fmap :: (a -> b) -> f a -> f b

在这里,f不是用作普通类型,而是用作类型构造函数,因此推断 kind is * -> *:kind您可以使用GHCi中的命令验证这一点:

> :kind Print
Print :: * -> Constraint
> :kind Functor
Functor :: (* -> *) -> Constraint 
于 2012-10-25T21:27:37.683 回答
9

当你说

class Print a where
   print' :: a -> String

你确保它a必须是一种类型,但是当你说

data A t = A t

您创建A了一个类型构造函数 -A不是类型,而是A Int,例如。A是类型上的一种函数,但aPrint 类中的 必须是类型值,而不是类型函数。

你可以做

instance Print (A Int) where
  print' a = "abc"

没关系,IO因为Functor该类要求类型构造函数。

class Functor f where
  fmap :: (a -> b) -> f a -> f b

可以看到,since f ais a type,fis a type constructor,就像IOand Aare一样。你将能够做到

instance Functor A where  -- OK, A is a constructor, Functor needs one
  fmap f (A x) = A (f x)

你将无法做到

instance Eq IO where -- not OK - IO is a constructor and Eq needs a type
    (==) = error "this code won't compile"

(为了避免与标准函数发生冲突,我使用print'了not 。)printprint

于 2012-10-25T21:13:42.260 回答
1

尝试在心里(或使用文本编辑器)用您在实例中使用的类型填充类定义中给出的类型。

从:

class Print a where
    print :: a -> String

data A t = A t

我们想要

instance Print A

所以,a在类型类定义中替换A我们所说的是一个实例,我们得到这个:

class Print A where
    print :: A -> String

哦哦。A -> String作为一种类型没有意义,因为函数类型箭头在左边接受一个类型,在右边接受一个类型,并为您提供函数类型。但A不是类型,因为您A使用data A t;声明 A t是任何类型的类型t,但是A类型构造函数。如果将它应用于类型,它可以创建类型,但A它本身是不同的。因此,您可以制作A t的实例Print,但不能制作A它本身。

那么为什么instance Functor IO起作用呢?让我们看一下类定义:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

IO现在让我们尝试替换f

class Functor IO where
    fmap :: (a -> b) -> IO a -> IO b

s最终IO应用于类型参数,所以一切正常。在这里,如果我们尝试创建一个具体类型IntA t例如Functor.

于 2012-10-26T04:29:21.173 回答