我一直在为WebAssembly指令定义GADT.许多这些指令构造函数具有相同的签名:
data Instruction result where
Add :: Instruction r -> Instruction r -> Instruction r
Sub :: Instruction r -> Instruction r -> Instruction r
Mul :: Instruction r -> Instruction r -> Instruction r
Run Code Online (Sandbox Code Playgroud)
使用正常值,您可以简单地为这些二元运算符声明类型别名:
type Binop r = Instruction r -> Instruction r -> Instruction r
Run Code Online (Sandbox Code Playgroud)
但是,当我在GADT定义中使用别名时:
{-# LANGUAGE GADTs #-}
module Data.Instruction where
type Binop r = Instruction r -> Instruction r -> Instruction r
data Instruction result where
Add :: Binop r
Sub :: Binop r
Mul :: Binop r
Run Code Online (Sandbox Code Playgroud)
它无法编译:
[6 of 6] Compiling Data.Instruction ( src/Data/Instruction.hs, .stack-work/dist/x86_64-osx/Cabal-2.0.1.0/build/Data/Instruction.o )
.../src/Data/Instruction.hs:8:5: error:
• Data constructor ‘Add’ returns type ‘Binop r’
instead of an instance of its parent type ‘Instruction result’
• In the definition of data constructor ‘Add’
In the data type declaration for ‘Instruction’
|
11 | Add :: Binop r
| ^
Run Code Online (Sandbox Code Playgroud)
有没有办法用GHC实现这一目标?如果没有,限制的原因是什么?
这是可能的,但不是以您所做的方式。这在这里确实有效:
\n\ntype Foo = Bar Int\n\ndata Bar a where\n Bar :: Foo\nRun Code Online (Sandbox Code Playgroud)\n\n...因为Foo实际上具有以下形式Bar a, 与a ~ Int。但是,这不会:
type Foo = Int -> Bar Int\n\ndata Bar a where\n Bar :: Foo\nRun Code Online (Sandbox Code Playgroud)\n\n它无法工作,因为 GADT 构造函数
\n\ndata Bar a where\n Bar :: Int -> Bar Int\nRun Code Online (Sandbox Code Playgroud)\n\n实际上并没有声明 \xe2\x80\x9cin 可逆函数\xe2\x80\x9dBar :: Int -> Bar Int。相反,它声明了如下内容:
data Bar\' a = Bar\' (a :~: Int) IntRun Code Online (Sandbox Code Playgroud)\n\n即,它封装了一个(运行时可读的)证明,证明a参数类型实际上是Int。GADT 语法将其隐藏在幕后,但这意味着您不能只Int -> Bar Int用类型同义词替换,因为该类型同义词不会如何封装此类型相等性证明。
...考虑一下,我不确定为什么我的第一个示例实际上有效,因为它似乎遇到了同样的问题...
\n| 归档时间: |
|
| 查看次数: |
120 次 |
| 最近记录: |