现在我正在尝试使用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
来构造LValue
s或RValue
s。不过,在模式匹配时,您仍然需要在语法上区分它们。
第二个是制作GADT:
data Side = L | R
data Value side where
Var :: String -> Value side
Lit :: String -> Value R