2017-06-04 38 views
0

我觉得这应该很容易,但我坚持了很长一段时间。为数据类型列表创建实例 - Haskell

haskell有可能为某些数据类型的列表创建一个类型的实例吗?

我想实现的是以下内容。

class Rename a where 
    findSub :: a -> a 

-- A 'normal' instance would look like this 
instance Rename Atom where 
    findSub ...... 

-- Now i want to acchieve something like this 
instance Rename ([] Atom) where 
    findSub ...... 

当我写这篇文章如何过我得到以下错误:

* Illegal instance declaration for `Rename [Atom]' 
     (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 `Rename ([] Atom)' 
Failed, modules loaded: none. 

我想知道如何解决这个问题,为什么这是不允许的。

在此先感谢。

回答

3

它只是需要一个语言扩展,因为这种形式的实例在技术上没有被Haskell 98标准所允许。当错误消息表示启用扩展时,通常只需执行[1]。 FlexibleInstances是一个非常普遍的接受和推广,所以只是把

{-# LANGUAGE FlexibleInstances #-} 

在文件的顶部。


另外,很多时候,这种情况下可以“递归”规定,在这种情况下你不需要的扩展,但除此之外,你得到免费的多个实例,更保证,因为类型比较一般。看看你是否可以定义

instance (Rename a) => Rename [a] where 
    findSub ... 

,而不是只使用一个事实,即aRename,而不是它是具体的Atom。当你可以用这种方式定义实例时,这是一个很好的信号,表明你的设计在正确的轨道上。


[1]有一些例外,如UndecidableInstancesIncoherentInstances,有时表明您对类型类的分辨率是如何工作的一个错误的观念。

+0

我不倾向于看到'UndecidableInstances'出现在错误的代码中;我倾向于在完美的代码中看到更多,Haskell的极其有限的终止标准不足以证明是好的。 – dfeuer

+0

@dfeuer,一旦你对类型类很熟悉,我同意,但是通常初学者往往会认为类型类的分辨率倒退或者比它强大得多(例如''实例向量=>数量类'等),这很快导致这些扩展被“需要”(尽管当它们被启用时它仍然不能按预期工作)。没有? – luqui

+0

我倾向于更多地考虑'OverlappingInstances','IncoherentInstances','AllowAmbiguousTypes'和(当不使用多参数类型类时)'FlexibleInstances'。但你也许是对的。 – dfeuer