我正在为一种小型编程语言编写解释器,AST看起来像这样:
data Value a = IntVal a Int | FloatVal a Float
data Expr a = AddExpr a (Value a) (Value a) | MulExpr a (Value a) (Value a)
我使用参数a
来存储每个术语的行号。有些函数接受带有注释的项,有些接受空项(用unit
代替a
),如下所示:
myFunction :: Value Int -> ...
myFunction = ...
myOtherFunction :: Value () -> ...
myOtherFunction = ...
但是,我发现另一种选择更清楚:
type Annotated b = b Int
type Bare b = b ()
然后,我可以像这样重写前面的两个函数:
myFunction :: Annotated Value -> ...
myFunction = ...
myOtherFunction :: Bare Value -> ...
myOtherFunction = ...
这个工作得很好,但是我还需要为具有相同特征的列表类型定义一个同义词:
type MyList a = [Value a]
现在,我想定义一个带注释的MyList
函数,如下所示:
myOtherOtherFunction :: Annotated MyList -> ...
myOtherOtherFunction = ...
然而,这不起作用。错误显示The type synonym ‘MyList’ should have 1 argument, but has been given none
。为什么这行不通呢?有没有更好的方法来定义这些类型?也许还有一些扩展?
Haskell在默认情况下有点迂腐,必须始终完全应用类型同义词,也就是说,如果不直接将其应用于具体的类型参数,就不能提到MyList
,因此不能有Annotated MyList
。这种限制的原因是部分应用的类型同义词可能被误用来形成图灵完全语言。哎呀……这将是一个痛苦的编译器。
Annotated MyList
来说有点傻,这是在对完全不引人注目的[Value Int]
进行两个简单替换之后解决的,因此应该工作,不是吗?确实如此,但是您需要启用一个语法扩展:
{-# LANGUAGE LiberalTypeSynonyms #-}
myOtherOtherFunction :: Annotated MyList -> ...
myOtherOtherFunction = undefined