[Haskell-beginners] Drawing Information from a function already defined

Brent Yorgey byorgey at seas.upenn.edu
Wed Jul 20 15:59:22 CEST 2011


On Wed, Jul 20, 2011 at 11:45:52PM +1000, Clockwork PC wrote:
> Greetings Haskell community,
> 
> This is my first ever post so please be gentle...

Hi Alexander, welcome!  I hope you will find that people here are
gentle whether it is your first post or 500th.

> Defined my function:
> 
> Prelude> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <-
> [1..10], a^2 + b^2 == c^2 ]
> 
> Tested my function:
> 
> Prelude> rightTriangles
> [(4,3,5),(3,4,5),(8,6,10),(6,8,10)]

Looks good.

> Now, I want to define a refinement of this that will only select values
> whose total is 24.
> 
> I could write it so:
> 
> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10],
> a^2 + b^2 == c^2,* a+b+c == 24*]
> 
> However, it seems like a bit of a waste if I already have "rightTriangles"
> defined.

Indeed!  In general Haskell offers lots of abstraction that makes it
easy not to repeat yourself, so this is a good intuition.

> I tried a few things, but none of them worked:
> 
> Prelude> let rightTriangles` = rightTriangles, a+b+c == 24

First of all, backtick ` cannot be used as part of an identifier
name.  Instead you probably want  rightTriangles'  (with a single
quote).

The second issue is that there is no way to "extend" a list
comprehension.  Once you have defined a list using a list
comprehension, all you have is the list -- there is no longer any way
to "reach inside" the definition and see that it was defined using a
list comprehension, much less extend or alter the definition.  So we
have to make do with manipulating the list rightTriangles itself.

First, you could simply write a new list comprehension, pulling values
from the original rightTriangles list, like so:

  rightTriangles' = [ (a,b,c) | (a,b,c) <- rightTriangles, a+b+c = 24 ]

Or you could use the 'filter' function.  As its first argument it
expects a *function* which returns a Bool (True or False) for each
element in the list, specifying whether to keep it (True) or throw it
away (False).  As its second argument it takes the list you want to
filter. So:

  rightTriangles' = filter sum24 rightTriangles
    where sum24 (a,b,c) = (a+b+c) == 24

Here the sum24 function decides whether to keep each triple (a,b,c):
we only want to keep those whose sum is equal to 24.

-Brent



More information about the Beginners mailing list