Re: [Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-02 Thread Dan
Hi Richard,

 Yeek.  Why do you want to do _that_?

Heh.  I've got a parser and I want to check what I've parsed (it's an
exercise in Write Yourself a Scheme in 48 Hours).

   check (Atom _) (Atom _) = True
   check (Bool _) (Bool _) = True
   check __= False

Yes I came up with this too, but it seemed ugly to create unnecessary
new values just to take them apart again.

   is_atom (Atom _) = True
   is_atom _= False

This is nicer.  It still requires listing out the possible
constructors (Bool, Atom ... the real code obviously has more).  I
don't like that, because I've already listed them out once, in the type
declaration itself.  Surely, I shouldn't have to list them out again?

 There are various meta-programming (Scrap Your Boilerplate,
 Template Haskell) approaches you can use to automate some of
 these.

You hit the nail on the head.  Why I am doing this is because of
boilerplate. Boilerplate gives me rashes and bulbous spots on the nose.

Consider the following Ruby code:

def check(zeClass, zeValue)
zeValue.is_a? zeClass
end

This does not require a new function for every class defined in Ruby.
(To be fair, though, the class of a Ruby object tells you precious
little, compared to a Haskell type constructor).

I figured there would be a clever Haskell idiom that would give me a
similarly concise route. Does it really require Template Haskell? I can
barely parse regular Haskell as it is..

Cheers,
- Dan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-02 Thread Ryan Ingram
On Tue, Jun 2, 2009 at 3:50 AM, Dan danielkc...@gmail.com wrote:
 You hit the nail on the head.  Why I am doing this is because of
 boilerplate. Boilerplate gives me rashes and bulbous spots on the nose.

 Consider the following Ruby code:

        def check(zeClass, zeValue)
                zeValue.is_a? zeClass
        end

 This does not require a new function for every class defined in Ruby.
 (To be fair, though, the class of a Ruby object tells you precious
 little, compared to a Haskell type constructor).

 I figured there would be a clever Haskell idiom that would give me a
 similarly concise route. Does it really require Template Haskell? I can
 barely parse regular Haskell as it is..

So the question is, why do you need to know if x is an Atom or a Bool?
 The Haskell idiom is to pattern match and just do what you want with
the data:

f (Atom s) = ...
f (Bool b) = ...

instead of

f x = if isAtom x then ... atomData x ... else ... boolData x ...

Alternatively, you can define a fold[1] once:

myval :: MyVal - (Bool - a) - (String - a) - a
myval (Bool b) bool atom = bool b
myval (Atom s) bool atom = atom s

f x = myval bool atom where
   bool b = ...
   atom s = ...

This is a small amount of boilerplate that you write once for each
type; it's possible to automate it with TH, but usually it's not worth
it, in my opinion.

Coming from Ruby (the same route I took to get to Haskell!), you
should be aware that Haskell does have somewhat more boilerplate
than Ruby, but it has its benefits as well.  I am a convert to the
Church of Purity and Type-Safety :)  And you can use type classes for
many metaprogramming tasks.

  -- ryan

[1] fold here is the general term for this type of function.  Examples are
foldr: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/GHC-Base.html#foldr
maybe: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Data-Maybe.html#maybe
either: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Data-Either.html#either
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-02 Thread wren ng thornton

Ryan Ingram wrote:

Dan danielkc...@gmail.com wrote:
 I figured there would be a clever Haskell idiom that would give me a
 similarly concise route. Does it really require Template Haskell? I can
 barely parse regular Haskell as it is..


[...]

Alternatively, you can define a fold[1] once:

myval :: MyVal - (Bool - a) - (String - a) - a
myval (Bool b) bool atom = bool b
myval (Atom s) bool atom = atom s

f x = myval bool atom where
   bool b = ...
   atom s = ...


In terms of boilerplate, this is often far and away the cleanest 
solution. I highly recommend if for Write Yourself A Scheme.



The one place where it falls down is when, for whatever reason, you end 
up having collections of MyVals which can't sensibly use some set of 
constructors. One common example is for type-checking compilers where 
you guarantee that ill-typed MyVals cannot be constructed (rather than 
doing a verification pass after construction to ensure they're well-typed).


If your type has this problem, using the fold approach often means 
writing dummy functions to throw errors on invalid inputs, which in turn 
means sacrificing much of the type safety you'd like (even if you use 
something like the Maybe or Error monads instead of _|_). A canonical 
Haskell trick here is to use GADTs to maintain your type invariants, 
rather than using plain ADTs. This technique isn't really suitable for a 
first pass at learning Haskell though.




[1] fold here is the general term for this type of function.  Examples are
foldr: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/GHC-Base.html#foldr
maybe: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Data-Maybe.html#maybe
either: 
http://haskell.org/ghc/docs/latest/html/libraries/base/src/Data-Either.html#either


Two more good resources for folds are:


* http://knol.google.com/k/edward-kmett/catamorphisms/

This has an implementation in Control.Morphism.Cata from 
category-extras[1], though the documentation is scarce. If you're 
interested in the theory of why folds look and work the way they do, 
then this knol is the best starting point. If you're familiar with OOP, 
a catamorphism is extremely similar to the recursive Visitor pattern.


The big difference you'll see between this generic solution and 
specialized catamorphisms (foldr, maybe, either,...) is that the 
specialized versions unpack the Algebra into separate arguments. Also, 
this generic solution defines MyVal types with open-recursive functors 
and explicit fixed-point operators, whereas the specialized versions 
just use Haskell's regular ability to define recursive types (since the 
result of |fmap (cata f)| is consumed immediately). Don't let these 
trees obscure the forest.



* http://www.cs.nott.ac.uk/~wss/Publications/DataTypesALaCarte.pdf

This paper presents an innovative solution to the expression problem 
of defining an open set of constructors for a type. It uses the same 
open-recursive functor trick as above and may provide some illustration 
of why we may want to bother with it. If you're hungry for more details, 
there's an interesting discussion of the paper at [2].



[1] http://hackage.haskell.org/packages/archive/category-extras/
[2] http://wadler.blogspot.com/2008/02/data-types-la-carte.html

--
Live well,
~wren
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-01 Thread Dan Cook

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.   
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.


What is the preferred way to do this, since neither of those functions  
compile?


Cheers,
- Dan
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-01 Thread Jason Dagit
Hi Dan,

On Mon, Jun 1, 2009 at 8:39 PM, Dan Cook danielkc...@gmail.com 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


You may be confusing yourself here on one point.  The type 'Bool' is already
defined by the prelude, but the data constructor is not.  So you are able to
create a data constructor for MyVal that is called Bool and contains a
Bool.  I think this distinction is leading to the next probem I see.  Type
signatures have to contain types and not values in Haskell.  'True' is a
value so it can't be placed in the type signature.  The type of True is
Bool.  So I think you meant to ask about:
check :: (Bool - MyVal) - MyVal - Bool

Now if you define this function the first parameter can be any function Bool
- MyVal, not just the data constructors of MyVal.  Also, the type of Atom
:: String - MyVal so you can't even pass it to 'check'.



 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.  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.


This strikes me as a job for template haskell, but the use of TH is beyond
what I can explain :)




 What is the preferred way to do this, since neither of those functions
 compile?


My preferred way, is just to define isAtom and isBool both with type MyVal
- Bool and use them where I need them.  There are a number of tools to
generate such things like DrIFT, TH, and maybe some others?

I hope that helps,
Jason
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Checking a value against a passed-in constructor?

2009-06-01 Thread Richard O'Keefe


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