将一个数据构造函数用于两种不同的类型



现在我正在尝试使用Haskell编写一个玩具语言前端。

有两个实体:

  • 右值-变量和整数文本(例如(
  • lvalue-仅限变量

我认为在数据结构中描述这一点最自然的方法是:

data LValue = Var String
data RValue = Var String | Lit Int

(我真的认为这是最好的方法——由于详尽的模式匹配,所以不够冗长和严格(但是ghc向我展示了一个错误:;Var"的多个声明;。

所以问题是:在Haskell中,描述我想要什么的最直接的方式是什么?

注意事项:11年前也有一个类似的问题,但没有很好的答案。但是11年来有什么变化吗?属于两种不同类型的一个值构造函数

还有一些其他方法;包装";像这样的数据构造函数中的LValue一次又一次(在不太像玩具的语言中(:

data LValue = Var String 
data RValue = LValue LValue | Lit Int

但我怀疑这是否是一种好方法:AST转换代码变得过于冗长。

我实际上认为你的建议是最好的:

newtype LValue = Var String -- newtype is slightly better here, I think
data RValue = LValue LValue | Lit Int

几乎可以肯定的是,任何时候你使用一个左值作为右值,你都希望以统一的方式处理所有的左值,所以你可能不需要或不想在那一刻进行第二级的模式匹配;换言之,我声称会有比你最初预期的更少的冗长。

基本上有两种选择。第一个是制作一个类:

newtype LValue = LVar String
data RValue = RVar String | Lit Int
class HasVariables ty where var :: String -> ty
instance HasVariables LValue where var = LVar
instance HasVariables RValue where var = RVar

通过这种方式,您可以使用var来构造LValues或RValues。不过,在模式匹配时,您仍然需要在语法上区分它们。

第二个是制作GADT:

data Side = L | R
data Value side where
Var :: String -> Value side
Lit :: String -> Value R

最新更新