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?"


_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to