Haskell中的“newtype”用于类型同义词。

6

我正在处理SAT相关的工作,我想要同时使用“和”和“或”。

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

但是当我使用它们时遇到了问题:
instance Satisfiable AndClause where ...
instance Satisfiable OrClause where ...

我收到了“Duplicate instance declarations.”的错误信息。它们是类型,而不是数据或类型构造函数,所以我认为我不能使用newtype来完成我想要的操作。有没有解决方案?

1个回答

22
问题在于您似乎想要两件相互冲突的事情:
1. 您希望相同类型有不同名称 2. 您希望编译器将这两个类型名称视为引用不同类型
根据领域,我认为您肯定不希望使用类型同义词,而是希望实际上有新类型(伴随有相应的类型构造函数)。如果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) = --...

(请注意我是在离开编译器的情况下输入这段话,但它基本上应该是正确的。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接