Drawing Information from a function already defined

Greetings Haskell community, This is my first ever post so please be gentle... Here's where I got to: Jumped into GHCi: GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. 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)] 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. I tried a few things, but none of them worked: Prelude> let rightTriangles` = rightTriangles, a+b+c == 24 <interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = rightTriangles | a+b+c == 24 <interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = [rightTriangles, a+b+c == 24] <interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = [rightTriangles | a+b+c == 24] <interactive>:1:21: parse error on input `=' Basically, I'm trying to work out how to draw data from a list already to hand. Alexander

On Wed, Jul 20, 2011 at 11:45:52PM +1000, Clockwork PC wrote:
Defined my function:
Prelude> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2 ]
...
Now, I want to define a refinement of this that will only select values whose total is 24.
...
Basically, I'm trying to work out how to draw data from a list already to hand.
This last part says it. You already know how to draw data from a list: you do it above when you pull, e.g., c from [1..10]. You actually do it three times (for a, b, and c). This time around, you have an existing list (named rightTriangles), and you want to pull (a,b,c) from it, rather than pulling a, b, and c from separate lists. Otherwise, it's much the same as what you were doing before. So the structure of it would look something like: let myTriangles = [ (a,b,c) | (a,b,c) <- rightTriangles, *condition* ] ^ a new name ^ same sort of output ^ from your existing list where *condition* is your "add up to 24" requirement, in the same form as the "a^2+b^2==c^2" requirement in your first list comprehension. Hope that helps. -john

Thanks to everyone for such a response! I'm overwhelmed.
Your suggestions were very helpful and I'd like to share my first success in
Haskell with you...
I wrote a little file triangle.hs that contains this:
rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 +
b^2 == c^2 ]
And then loaded it in GHCi:
*GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :l triangle
[1 of 1] Compiling Main ( triangle.hs, interpreted )
Ok, modules loaded: Main.
*Main>
*
Then I tried the first approach:
*Main> let myTriangle = [ (a,b,c) | (a,b,c) <- rightTriangles, a+b+c == 24 ]
*Main> myTriangle
[(8,6,10),(6,8,10)]
I also tried the second simple approach:
*Main> let myTriangles2 = filter sum24 rightTriangles where sum24 (a,b,c) =
(a+b+c) == 24
*Main> myTriangles2
[(8,6,10),(6,8,10)]
Hooray! Thank you, John and Brent.
Thank you also to Felipe for your correction.
And finally, think you to Aditya. I don't really understand Monads yet, but
when I get to that chapter in my guide I'll refer to your email many times,
I'm sure.
Thanks again to all you lovely people for helping me with my query :-)
Alexander
On Wed, Jul 20, 2011 at 23:57, john melesky wrote:
On Wed, Jul 20, 2011 at 11:45:52PM +1000, Clockwork PC wrote:
Defined my function:
Prelude> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2 ]
...
Now, I want to define a refinement of this that will only select values whose total is 24.
...
Basically, I'm trying to work out how to draw data from a list already to hand.
This last part says it. You already know how to draw data from a list: you do it above when you pull, e.g., c from [1..10]. You actually do it three times (for a, b, and c).
This time around, you have an existing list (named rightTriangles), and you want to pull (a,b,c) from it, rather than pulling a, b, and c from separate lists. Otherwise, it's much the same as what you were doing before.
So the structure of it would look something like:
let myTriangles = [ (a,b,c) | (a,b,c) <- rightTriangles, *condition* ] ^ a new name ^ same sort of output ^ from your existing list
where *condition* is your "add up to 24" requirement, in the same form as the "a^2+b^2==c^2" requirement in your first list comprehension.
Hope that helps.
-john
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

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

On Wed, Jul 20, 2011 at 10:45 AM, Clockwork PC
Defined my function:
Prelude> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2 ]
Minor correction: rightTriangles is not a function, it is a value. Note that it takes no arguments. Cheers, =) -- Felipe.

Hi,
For adding constraints I think that using List as a monad is the most
flexible way to go. The first two functions below show the monadic
equivalent of your first two list comprehension examples. The third
shows how to add constraints without having to rewrite the function.
The first two function could have been expressed using only the third
but are presented to show how it was built.
-deech
import Control.Monad
-- triples' == [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10]]
triples' = do
a <- [1 .. 10]
b <- [1 .. 10]
c <- [1 .. 10]
return (a,b,c)
-- triples'' (\(a,b,c) -> a + b + c == 24) ==
-- [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a + b + c == 24]
triples'' constraint = do
a <- [1 .. 10]
b <- [1 .. 10]
c <- [1 .. 10]
guard $ constraint (a,b,c)
return (a,b,c)
-- triples''' [\(a,b,c) -> a^2 + b^2 == c^2, \(a,b,c) -> a + b + c == 24] ==
-- [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 =
c^2, a + b + c == 24]
triples''' :: [(Int,Int,Int) -> Bool] -> [(Int,Int,Int)]
triples''' constraints = do
a <- [1 .. 10]
b <- [1 .. 10]
c <- [1 .. 10]
sequence_ $ map (\constraint -> guard $ constraint (a,b,c)) constraints
return (a,b,c)
On Wed, Jul 20, 2011 at 8:45 AM, Clockwork PC
Greetings Haskell community,
This is my first ever post so please be gentle...
Here's where I got to:
Jumped into GHCi:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done.
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)]
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.
I tried a few things, but none of them worked:
Prelude> let rightTriangles` = rightTriangles, a+b+c == 24
<interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = rightTriangles | a+b+c == 24
<interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = [rightTriangles, a+b+c == 24]
<interactive>:1:21: parse error on input `=' Prelude> let rightTriangles` = [rightTriangles | a+b+c == 24]
<interactive>:1:21: parse error on input `='
Basically, I'm trying to work out how to draw data from a list already to hand.
Alexander
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (5)
-
aditya siram
-
Brent Yorgey
-
Clockwork PC
-
Felipe Almeida Lessa
-
john melesky