I got a custom data type schematically defined like this:
data Foo = Foo
{ f1 :: Int
, f2 :: b
, f3 :: c
}
What i need to do
Attach a String to every function recorded in Foo. That was pretty clear in my head that it was trivial due to haskell polymorphism.
First try: classes
class Value a where
val :: a -> String
class Query e where
queries :: (Value a) => [(e -> a, String)]
instance Value Int where val = show
instance Query Foo where
queries =
[ (f1, "function one")
, (other records of Foo…)
]
Which doesn't work. I'm not sure i figured out why. But i think ghc expects a function of type (Foo -> a) but gets a function of type (Foo -> Int). So, the polymorphism doesn't apply here.
Second try: pattern matching
keyOf :: (Foo -> a) -> String
keyOf f1 = "function one"
keyOf f2 = "function two"
keyOf f3 = "function three"
keyOf _ = "unknown function"
I was quite satisfied seeing it would compile. Then, in ghci:
λ keyOf f2 = "function one"
Can't pattern match against a function name, obviously…
EDIT: Why i need to do it
Construct a query string like this:
"(keyOf f1)=(f1 Foo), (keyOf f2)=(f2 Foo), (keyOf f3)=(f3 Foo)"
More generally, fold every function recorded in Foo with the String associated with it, and it's result. Example:
exampleFoo :: Foo
exampleFoo = Foo "one" "two" "three"
assocs = [(f1, "function one"), (f2, "function two"), (f3, "function three")]
result == "function one=one, function two=two, function three=three"
Now, i really wonder if that kind of trick is doable without involving meta-programming (like TemplateHaskell) in haskell. Any options i didn't consider ? Thanks.