Haskell"newtype"用于类型同义词

Xod*_*rap 6 haskell types

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

type AndClause = [Literal]
type OrClause  = [Literal]
Run Code Online (Sandbox Code Playgroud)

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

instance Satisfiable AndClause where ...
instance Satisfiable OrClause where ...
Run Code Online (Sandbox Code Playgroud)

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

Jon*_*ing 22

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

  1. 您需要相同类型的不同名称
  2. 您希望编译器将这两个类型名称理解为引用不同的类型

基于域,我认为您当然不希望使用类型同义词,并且您确实需要实际的新类型(带有类型构造函数).如果AndClause是同义词[Literal],并且OrClause是其同义词[Literal],那么通过传递属性,AndClause并且OrClause是相互同义的.因此,编译器没有理由区分它们(因此,不存在多态性).

你真正想要的是两种表现不同的不同类型,为此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) = --...
Run Code Online (Sandbox Code Playgroud)

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

data Prop = And [Literal]
          | Or [Literal]

instance Satisfiable Prop where
  satisfy (And l:ls) = --...
  satisfy (Or l:ls) = --...
Run Code Online (Sandbox Code Playgroud)

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

  • 使用ADT的+1.这是标准解决方案. (7认同)