Haskell `实例`用于具体类型而不是typeclass?
我定义了一个简单的列表类型:Haskell `实例`用于具体类型而不是typeclass?,haskell,typeclass,Haskell,Typeclass,我定义了一个简单的列表类型: data MyList a = End |Entry a (MyList a) 而不是派生(Show)我为所有MyList a明确地实现了这一点,其中a是Show的一个实例 instance Show a => Show (MyList a) where show End = "" show (Entry a l) = (show a) ++","++(show l) 这个很好用。现在我想改变这种情况,只有
data MyList a = End
|Entry a (MyList a)
而不是派生(Show)
我为所有MyList a
明确地实现了这一点,其中a
是Show
的一个实例
instance Show a => Show (MyList a)
where show End = ""
show (Entry a l) = (show a) ++","++(show l)
这个很好用。现在我想改变这种情况,只有MyList String
是Show
的一个实例,为此我编写了
instance Show (MyList String)
where show End = ""
show (Entry a l) = a ++","++(show l)
但这导致了一个错误,我不理解:
Illegal instance declaration for `Show (MyList String)'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use FlexibleInstances if you want to disable this.)
In the instance declaration for `Show (MyList String)'
有人能解释一下为什么这不起作用,以及这个错误告诉我什么吗?这个错误告诉您,standard Haskell不允许这种实例定义。正如上面所说,
所有实例类型的格式必须为(T a1…an)
其中a1。。。A是*不同类型的变量*,
每个类型变量在实例头中最多出现一次。
其中一个原因是,如果您同时保留两个实例定义,编译器将不知道为MyList String
选择哪一个,因为它们都匹配。(您可能还想看一下。)
在实例类型的形式上有这样的约束可以保证类型检查总是终止的,当然也有一些有效的、可类型检查的程序的实例不是这种形式的,这就是它的工作原理:Haskell中的一些限制是保守的
在您的特定情况下,只需按照编译器的建议执行(即启用
FlexibleInstances
)即可实现此功能,并且此扩展在终止方面是安全的。因此,如果不启用FlexibleInstances
,我只能对整个类型类执行显示,而对特定类型的构造函数则不行(例如,您的MyList::*->*
)您只能为整个“类型族”实现类(例如Show
)形式为MyList a
,而不是针对特定的个人,如MyList String
或MyList Bool
。顺便说一句,这正是Show
具有hacky方法的原因。您希望显示Char
列表与所有其他类型的列表不同,但您不能只实现separate在标准Haskell中显示[Char]
实例。