GADT 中任何“DataKind”的列表
List of any `DataKind` in GADT
免责声明
GADTs 和 DataKinds 对我来说是未开发的领域,所以我不知道它们的一些限制和功能。
问题
所以我正在为 JavaScript 代码发射器编写 AST,并且我已经确定了表达式之间的一个边缘情况,即它们可以是引用也可以不是。因此,我使用 GADTS 和数据种类来键入 JavaScript 表达式语义的这一方面。 ast 看起来像这样。
表达式 AST 的子集
-- at the moment I'm just using a bool to identify if the expression
-- behaves as an reference, but I'll probably change it due to the fact
-- a bool is pretty vague
data JSExp :: Bool -> * where
JSNumber :: Double -> JSExp False
JSBool :: Bool -> JSExp False
JSReference :: Text -> JSExp True
JSProperty :: JSExp a -> Text -> JSExp True
JSAssign :: JSExp True -> JSExp b -> JSExp b
这看起来很好,很漂亮,因为赋值表达式要求第一个表达式是引用,例如 属性 表达式 ("test".shadyProperty
) 或 reference/identifier.
问题
现在我想添加一个数组文字表达式,在 JavaScript 中,这个列表中的内容无关紧要,所以像这样的列表是合法的
[a, 1, true, a.b]
但是在我的 AST 中这是不合法的,因为列表中有多种类型
data JSExp :: Bool -> * where
-- ...
JSArray :: [JSExp ???] -> JSExp False
let aref = JSReference "a"
in JSArray [aref, JSNumber 2, JSBool True, JSProp aref "b"]
用什么代替 ???
类型?当我想为 JSObject 和 JSFunctionCall 构建构造函数时会出现类似的问题,因为它们也是表达式。
伊德里斯的灵魂
在 Idris ???
中看起来像这样。
data JSExp : Bool -> Type where
JSArray : List (JSExp _) -> JSExp False
JSNumber : Float -> JSExp False
JSBool : Bool -> JSExp False
-- ...
潜在的灵魂
环绕类型
一个与 Idris 不同的灵魂,应该有这样的包装器类型
data JSExpWrap = Refs (JSExp True) | NoRef (JSExp False)
这会使我的图书馆 api 变得恶心,这不是我要找的。
总结
我正在寻找在 Idris 中找到的等效项,以及对解决方案含义的解释。如果没有等效项,那么我正在寻找的是下一个最好的解决方案。
您可以使用存在主义:
{-# LANGUAGE GADTs, DataKinds, PolyKinds #-}
data Exists :: (k -> *) -> * where
This :: p x -> Exists p
data JSExp :: Bool -> * where
...
JSArray :: [Exists JSExp] -> JSExp False
test = let aref = JSReference "a"
in JSArray [This aref, This (JSNumber 2), This (JSBool True), This (JSProperty aref "b")]
或者加点糖:
infixr 5 !:
(!:) :: p x -> [Exists p] -> [Exists p]
x !: xs = This x : xs
test = let aref = JSReference "a"
in JSArray $ aref !: JSNumber 2 !: JSBool True !: JSProperty aref "b" !: []
免责声明
GADTs 和 DataKinds 对我来说是未开发的领域,所以我不知道它们的一些限制和功能。
问题
所以我正在为 JavaScript 代码发射器编写 AST,并且我已经确定了表达式之间的一个边缘情况,即它们可以是引用也可以不是。因此,我使用 GADTS 和数据种类来键入 JavaScript 表达式语义的这一方面。 ast 看起来像这样。
表达式 AST 的子集
-- at the moment I'm just using a bool to identify if the expression
-- behaves as an reference, but I'll probably change it due to the fact
-- a bool is pretty vague
data JSExp :: Bool -> * where
JSNumber :: Double -> JSExp False
JSBool :: Bool -> JSExp False
JSReference :: Text -> JSExp True
JSProperty :: JSExp a -> Text -> JSExp True
JSAssign :: JSExp True -> JSExp b -> JSExp b
这看起来很好,很漂亮,因为赋值表达式要求第一个表达式是引用,例如 属性 表达式 ("test".shadyProperty
) 或 reference/identifier.
问题
现在我想添加一个数组文字表达式,在 JavaScript 中,这个列表中的内容无关紧要,所以像这样的列表是合法的
[a, 1, true, a.b]
但是在我的 AST 中这是不合法的,因为列表中有多种类型
data JSExp :: Bool -> * where
-- ...
JSArray :: [JSExp ???] -> JSExp False
let aref = JSReference "a"
in JSArray [aref, JSNumber 2, JSBool True, JSProp aref "b"]
用什么代替 ???
类型?当我想为 JSObject 和 JSFunctionCall 构建构造函数时会出现类似的问题,因为它们也是表达式。
伊德里斯的灵魂
在 Idris ???
中看起来像这样。
data JSExp : Bool -> Type where
JSArray : List (JSExp _) -> JSExp False
JSNumber : Float -> JSExp False
JSBool : Bool -> JSExp False
-- ...
潜在的灵魂
环绕类型
一个与 Idris 不同的灵魂,应该有这样的包装器类型
data JSExpWrap = Refs (JSExp True) | NoRef (JSExp False)
这会使我的图书馆 api 变得恶心,这不是我要找的。
总结
我正在寻找在 Idris 中找到的等效项,以及对解决方案含义的解释。如果没有等效项,那么我正在寻找的是下一个最好的解决方案。
您可以使用存在主义:
{-# LANGUAGE GADTs, DataKinds, PolyKinds #-}
data Exists :: (k -> *) -> * where
This :: p x -> Exists p
data JSExp :: Bool -> * where
...
JSArray :: [Exists JSExp] -> JSExp False
test = let aref = JSReference "a"
in JSArray [This aref, This (JSNumber 2), This (JSBool True), This (JSProperty aref "b")]
或者加点糖:
infixr 5 !:
(!:) :: p x -> [Exists p] -> [Exists p]
x !: xs = This x : xs
test = let aref = JSReference "a"
in JSArray $ aref !: JSNumber 2 !: JSBool True !: JSProperty aref "b" !: []