为什么不能(完全)使用其他类型的同义词来应用具有参数的类型同义词?

Bak*_*riu 4 haskell types

我们可以使用参数定义类型同义词,这与实际类型一起使用时效果很好:

type MyType t = t String String

data Test a b = Test a b

f :: MyType Test
f = undefined

main = undefined
Run Code Online (Sandbox Code Playgroud)

编译这会导致没有错误:

$ghc --make test.hs                                           
[1 of 1] Compiling Main             ( test.hs, test.o )                                          
Linking test ...   
Run Code Online (Sandbox Code Playgroud)

但是,当Test类型为同义词时,这不起作用:

type MyType t = t String String

data Test a b = Test a b

type Test' a b = Test a b

f :: MyType Test'
f = undefined

main = undefined
Run Code Online (Sandbox Code Playgroud)

这给出了以下错误:

$ghc --make test.hs
[1 of 1] Compiling Main             ( test.hs, test.o )

test.hs:7:6:
    Type synonym Test' should have 2 arguments, but has been given none
    In the type signature for `f': f :: MyType (Test')
Run Code Online (Sandbox Code Playgroud)

令我百思不解的是,Test' 正在被应用到两个参数,所以为什么GHC抱怨我没有传递参数?

不应该键入同义词是完全透明的,不可能与其他类型区分?

有没有办法达到预期的行为?

Bak*_*riu 12

根据Haskell报告,类型同义词不能部分应用:

类型T同义词声明引入的类型构造函数符号不能部分应用; 在T没有完整参数的情况下使用它是一个静态错误.

特别是扩展类型同义词之前检查这一点,这意味着在表达式中:

MyType Test'
Run Code Online (Sandbox Code Playgroud)

在扩展之前执行检查MyType,因此Test'部分地应用结果.

然而,这可能实现使用GHC这种行为LiberalTypeSynonyms的延伸.此扩展将类型同义词视为宏,它们在不进行任何检查的情况下进行扩展,然后类型检查器将查看类型同义词是否已部分应用.

在类型同义词扩展之前仍然进行类型推断.

请注意,即使在这种情况下也不能部分应用类型同义词,例如:

Test' Int
Run Code Online (Sandbox Code Playgroud)

仍然是一个错误.但是,您现在可以使用类型同义词完全应用其他类型的同义词而不会收到错误

允许部分应用类型同义词会使类型推断变得不可判定,因此不可能轻松地在该方向上扩展类型系统.