
On 2 Jun 2009, at 3:39 pm, Dan Cook wrote:
Hi, (Relatively new to Haskell here ..)
So I have the following:
data MyVal = Atom String | Bool Bool
And I want to do something like this
check :: (Bool -> MyVal) -> MyVal -> True check f (f x) = True check _ _ = False
What that means is I want to pass a MyVal constructor and a MyVal, and return True if the second argument was constructed with the first.
Yeek. Why do you want to do _that_? You could quite easily determine whether two values were constructed with the _same_ constructor: check (Atom _) (Atom _) = True check (Bool _) (Bool _) = True check _ _ = False and instead of passing in "a constructor" pass in "an example of a term constructed by that constructor". So instead of check Atom foo, do check (Atom undefined) foo instead of check Bool bar, do check (Bool undefined) bar Another approach is to write a boolean function for each constructor, e.g., is_atom (Atom _) = True is_atom _ = False is_bool (Bool _) = True is_bool _ = False and pass one of these instead of a constructor: check :: (MyVal -> Bool) -> MyVal -> Bool check f x = f x which makes the check function itself pointless.
More generally, I'd like to be able to do
genCheck :: (* -> MyVal) -> MyVal -> True genCheck f (f x) = True genCheck _ _ = False
So that I can pass in _any_ MyVal constructor and let the function just check if the second argument was constructed with the first, without caring which constructor it is.
There are some very high-powered things you can do in Haskell these days which would let you get closer to this than most people would be happy reading. We can use the same idea of passing an example. So given data Biffo x y z = Ping x | Pong y z | Pang x y z you can easily write check (Ping _) (Ping _) = True check (Pong _ _) (Pong _ _) = True check (Pang _ _ _) (Pang _ _ _) = True check _ _ = False called as check (Ping undefined) foo or check (Pong undefined undefined) bar or check (Pang undefined undefined undefined) or much better, go the Boolean function route: is_ping (Ping _) = True is_ping _ = False is_pong (Pong _ _) = True is_pong _ = False is_pang (Pang _ _ _) = True is_pang _ = False and use one of these functions whenever you want something you can use to check for a particular constructor. There are various meta-programming ("Scrap Your Boilerplate", "Template Haskell") approaches you can use to automate some of these. The first step is the step backwards where you ask "why am I trying to do this?"