繁体   English   中英

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

[英]Why can't I make an instance with this unparameterized type?

为什么这段代码是正确的

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"

这是因为种类不匹配。 常规类型有类型* ,而类型构造函数(如AIO具有类型* -> * ,表示它们需要类型参数才能返回类型。

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

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

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

> :kind Print
Print :: * -> Constraint
> :kind Functor
Functor :: (* -> *) -> Constraint 

当你说

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

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

data A t = A t

你使A成为一个类型构造函数 - 例如, A不是一个类型,而是A Int A是一种对各类功能,但a在打印类必须是一个类型值,不是一个类型的功能。

你可以做到

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

它适用于IO因为Functor类要求输入类型构造函数。

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

你可以看到,因为fa是一个类型, f是一个类型构造函数,就像IOA一样。 你能做到的

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'而不是print来避免与标准功能print冲突。)

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

从:

class Print a where
    print :: a -> String

data A t = A t

我们想要

instance Print A

因此,替代a在类型类定义为A我们要说的是instnace,我们得到这样的:

class Print A where
    print :: A -> String

嗯,哦。 A -> String作为一种类型没有意义,因为函数类型箭头左侧是一个类型,右侧是一个类型,并为您提供函数类型。 但是A不是一个类型,因为你用data A t声明了A ; 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

IO最终应用于类型参数,因此一切正常。 如果我们尝试使用IntA t这样的具体类型作为Functor的实例,那么我们会遇到问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM