Haskell“newtype”用于类型同义词

时间:2011-04-15 22:36:33

标签: haskell types

我正在做SAT的一些事情,我希望同时拥有“和”和“或”条款。

type AndClause = [Literal]
type OrClause  = [Literal]

但是当我使用它时我遇到了问题:

instance Satisfiable AndClause where ...
instance Satisfiable OrClause where ...

给我“重复的实例声明”。它们是类型,而不是数据或类型构造函数,所以我认为我不能使用newtype来做我想要的。有没有解决方案?

1 个答案:

答案 0 :(得分:22)

问题是你似乎想要同时发生两件相互冲突的事情:

  1. 您需要相同类型的不同名称
  2. 您希望编译器将这两个类型名称理解为引用不同的类型
  3. 基于域名,我认为您当然不希望使用类型同义词,并且您确实需要实际的新类型(带有类型构造函数)。如果AndClause[Literal]的同义词,而OrClause[Literal]的同义词,则传递属性AndClauseOrClause是相互同义。因此,编译器没有理由区分它们(因此,不存在多态性)。

    你真正想要的是两种表现不同的不同类型,newtype可以做得很好:

    newtype AndClause = AndClause [Literal]
    newtype OrClause = OrClause [Literal]
    
    instance Satisfiable AndClause where
      satisfy (AndClause l:ls) = --...
    
    instance Satisfiable OrClause where
      satisfy (OrClause l:ls) = --...
    

    但是,更好的想法可能是使其成为代数数据类型:

    data Prop = And [Literal]
              | Or [Literal]
    
    instance Satisfiable Prop where
      satisfy (And l:ls) = --...
      satisfy (Or l:ls) = --...
    

    (请注意,我输入的是远离编译器,但基本上应该是正确的。)