我的功能需要Type
:
data MyType = IntT | BoolT | OtherT
typeToMyType :: Type -> MyType
如何编写一个表明我想要匹配Int
类型的模式?
[t| GHC.Types.Int |]
会创建Q Type
类型的值,但是尽管经过数小时的挣扎,我仍然无法强制进行模式匹配拼接。
我也试过在警卫中使用它:
| $( do tI <- [t| GHC.Types.Int |]; [| t == tI |] ) = ...
但是抱怨:
No instance for (Language.Haskell.TH.Syntax.Lift Type)
arising from a use of `Language.Haskell.TH.Syntax.lift'
In the expression: Language.Haskell.TH.Syntax.lift tI
In a stmt of a 'do' block:
[| t == tI |]
pending(rn) [tI]
In the expression:
do { tI <- [t| Int |];
[| t == tI |]
pending(rn) [tI] }
可能更简单的方法是:
typeToMyType :: Type -> MyType
typeToMyType (ConT $(''Int)) = NumberT
但是:
Couldn't match type `Name' with `Q Pat'
Expected type: PatQ
Actual type: Name
In the expression: ''Int
In the splice: $(''Int)
我不知道这意味着什么。
我想“解析”一个函数签名来创建Q Dec
。我使用String
作为原型:
gen ["Int", "Int"] "luaOpMinus" '-
======>
Eval.hs:24:3-38
luaOpMinus [Number x_a98F, Number x_a98G]
= (return $ [Number ((-) x_a98F x_a98G)])
正如你所看到的,它将一个函数Int -> Int -> Int
注释为一个函数["Int", "Int"]
,注释为值[LuaValue] -> LuaValue
(我现在省略了返回类型) - 所以它很容易从Lua调用。但是,手工打字签名很乏味,所以我想从reify
中提取出来。
问题是虽然我可以清楚地看到reify
给我的内容:
Prelude Language.Haskell.TH Data.Bits> $(reify 'bit >>= stringE . show)
"ClassOpI Data.Bits.bit (ForallT [PlainTV a_1627400821] [ClassP Data.Bits.Bits [VarT a_1627400821]] (AppT (AppT
ArrowT (ConT GHC.Types.Int)) (VarT a_1627400821))) Data.Bits.Bits (Fixity 9 InfixL)"
我无法写出 (ConT GHC.Types.Int)
模式。
答案 0 :(得分:2)
typeToMyType :: Type -> MyType typeToMyType (ConT $(''Int)) = NumberT
您不需要$(...)
,因为''Int
已经有Name
类型。
typeToMyType :: Type -> MyType
typeToMyType (ConT t) | t == ''Int = IntT
| t == ''Bool = BoolT
typeToMyType _ = OtherT
由于某些原因,GHC不喜欢模式中的''Int
语法,因此我不得不将其移至模式保护。