为什么这个类型定义是非法的?

4

我正在编写一个小型编程语言的解释器,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 存储每个术语的行号。一些函数接受带注释的术语,而另一些则接受空的术语(将a 替换为 unit), 如下所示:

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 = ...

然而,这并不起作用。错误消息显示:“类型同义词‘MyList’应该有1个参数,但却没有给出”。为什么会这样?有更好的定义这些类型的方法吗?也许可以使用某些扩展功能?

2
类型同义词不能用作高阶类型构造函数。它们必须始终完全饱和。 - Fyodor Soikin
1个回答

9

Haskell默认情况下有一些严谨的规定,即类型同义词必须始终完全应用,即不能提及MyList而不直接将其应用于具体的类型参数,因此你不能拥有Annotated MyList。这个限制的原因是,部分应用的类型同义词可能会被误用来形成图灵完备语言。糟糕... 这将对编译器造成很大的负担。

话虽如此,显然对于Annotated MyList而言,这有点傻,因为它只需要进行两次简单的替换就可以变成非常普通的[Value Int],所以它应该可以工作,不是吗?的确如此,但你需要启用一种语法扩展:

{-# LANGUAGE LiberalTypeSynonyms #-}

myOtherOtherFunction :: Annotated MyList -> ...
myOtherOtherFunction = undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接