[英]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"
这是因为种类不匹配。 常规类型有类型*
,而类型构造函数(如A
或IO
具有类型* -> *
,表示它们需要类型参数才能返回类型。
在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
是一个类型构造函数,就像IO
和A
一样。 你能做到的
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
最终应用于类型参数,因此一切正常。 如果我们尝试使用Int
或A t
这样的具体类型作为Functor
的实例,那么我们会遇到问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.