Question

Does anyone know if there's a function in Haskell which does something like this:

"Int" -> Int

"String" -> String

"Bool" -> Bool

ie. it takes a string representation of a type constructor name, and converts it to the actual type constructor, both in an expression and in a pattern.

edit: My overall goal is to simplify something like:

transExp (Add exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [IAdd]

transExp (Sub exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [ISub]

Into a single pattern match, so basically convert Add or Sub to a string, add an "I" to the front, and convert it back to a type.

Was it helpful?

Solution

There is a much better way to refactor your code here without any Template Haskell or reflection shenanigans by simply joining your Add and Sub cases into one:

data BinOp = Add | Sub | ...

data Expr = ...
          | BinOp BinOp Expr Expr
          | ...

transExp (BinOp op exp1 exp2) vars
    = transExp exp1 vars ++ transExp exp2 vars ++ [transOp op]
...

transOp Add = IAdd
transOp Sub = ISub

This way, we're using the data type to express directly the fact that binary operators are related, and therefore have similar translations. You can still pattern match on BinOp Add exp1 exp2 if you want to make a special case for addition somewhere.

OTHER TIPS

In which context? There is Template Haskell and Data.Typeable, but for an actually helpful answer you need to provide more details.

Well, here's the problem.

"String" -> String

That's gibberish in Haskell-land, because "String" is a value but String is a type. So you might try this:

String -> a

This doesn't do what you want. You should learn how to read type signatures, because if you can't read type signatures, you're going to be badly handicapped at Haskell. The above type means, "Give me a string and I can give you a value of any type you request." There is a function in the prelude with this signature, it is called error, which is not what you want.

It sounds like you want something along these lines:

String -> TypeRep

Sorry, no such function. TypeRep does not instantiate the Read class.

What are you actually trying to do here? If you tell us what you are actually trying to do, we can help you with that problem rather than try to help with this problem.

You can't do it, because strings are runtime data and types have to be entirely resolved at compile time. The best you can probably do with your example is a helper function to eliminate some of the duplication:

helper exp1 exp2 vars op = transExp exp1 vars ++ transExp exp2 vars ++ [op]
transExp (Add exp1 exp2) vars = helper exp1 exp2 vars IAdd
transExp (Sub exp1 exp2) vars = helper exp1 exp2 vars ISub

But this may not actually be very useful in the long term, depending on how many cases you have.

In general, pattern matching is something that runs against type structures, so it has to be spelled out at compile type against concrete type constructors. This is the price you have to pay for having a really solid static type system.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top