Reputation: 39390
I have a function that takes a Type
:
data MyType = IntT | BoolT | OtherT
typeToMyType :: Type -> MyType
How can I write a pattern that would state I want to match on the type of Int
?
[t| GHC.Types.Int |]
will create a value of type Q Type
, but despite hours of struggling I was unable to force into a pattern match splice.
I've tried to use it in a guard as well:
| $( do tI <- [t| GHC.Types.Int |]; [| t == tI |] ) = ...
But that complains about:
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] }
A perhaps simpler approach would be to:
typeToMyType :: Type -> MyType
typeToMyType (ConT $(''Int)) = NumberT
But then:
Couldn't match type `Name' with `Q Pat'
Expected type: PatQ
Actual type: Name
In the expression: ''Int
In the splice: $(''Int)
I have no idea what that means.
I want to "parse" a function signature to create a Q Dec
. I've used String
for a prototype:
gen ["Int", "Int"] "luaOpMinus" '-
======>
Eval.hs:24:3-38
luaOpMinus [Number x_a98F, Number x_a98G]
= (return $ [Number ((-) x_a98F x_a98G)])
As you can see, it turns a function Int -> Int -> Int
, annotated with a value ["Int", "Int"]
(I've omitted the return type for now), into a function [LuaValue] -> LuaValue
- so that it can be called from Lua easily. Typing signatures by hand is tedious, though, so I wanted to extract that from reify
.
The problem is that while I can read what reify
gives me perfectly clearly:
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)"
I can't write the (ConT GHC.Types.Int)
pattern.
Upvotes: 4
Views: 552
Reputation: 795
typeToMyType :: Type -> MyType typeToMyType (ConT $(''Int)) = NumberT
You don't need the $(...)
, since ''Int
already has type Name
.
typeToMyType :: Type -> MyType
typeToMyType (ConT t) | t == ''Int = IntT
| t == ''Bool = BoolT
typeToMyType _ = OtherT
For some reason GHC doesn't like the ''Int
syntax in the pattern, so I had to move it to a pattern guard.
Upvotes: 2