Bartek Banachewicz
Bartek Banachewicz

Reputation: 39390

How to create a pattern match for Int in a function taking a Type?

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?

What have I tried?

1

[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] }

2

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.

What do I (even) need it for?

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

Answers (1)

gelisam
gelisam

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

Related Questions