2015-10-17 111 views
2

我是Haskell的初学者,正在解析和构建AST。我想知道如何定义类型如下:使一种类型成为一种类型或另一种类型

A Value可以是IdentifierLiteral。现在,我只是有一种Value有两个构造函数(取标识符的名称和字符串常量的值分别为):

data Value = Id String 
      | Lit String 

不过,后来想创建一个表示在一个分配的类型AST,所以我需要像

data Assignment = Asgn Value Value 

但显然,我总是想一个Assignment的第一部分,始终是一个Identifier!所以我想我应该让IdentifierLiteral不同的类型,以便更好地辨别事情:

data Identifier = Id String 
data Literal = Lit String 

但我怎么现在定义Value?我thaught的是这样的:

-- this doesn't actually work... 
data Value = (Id String) -- How to make Value be either an Identifier 
      | (Lit String) -- or a Literal? 

我知道我可以简单地做

data Value = ValueId Identifier 
      | ValueLit Literal 

但是这让我觉得有点unelegant和让我不知道是否有更好的解决办法?

+2

你可能想看看[GADTs](https://en.wikibooks.org/wiki/Haskell/GADT)。既然'Id'和'Lit'现在都是基于'String'的,现在你可能想用一些额外的参数来区分这两种类型(可能是一个幻象类型变量)。 –

+4

我不认为数据值= ValueId标识符| ValueLit Literal'不够好看。你不喜欢它什么? - 顺便提一下,注意通常我们更喜欢编写'newtype Identifier = Id String',而不是'data'等价。它更高效一些('数据'总是会产生一个额外的thunk间接层)。 – leftaroundabout

回答

0

我首先尝试重构我的类型,以便能够使用GADT来完成它,但最终,更简单的解决方案就是使用leftroundabout的建议。无论如何,我想这不是“不雅”。

相关问题