Understanding A bit of Haskell - haskell

I have a quick question about Haskell. I've been following Learn You a Haskell, and am just a bit confused as to the execution order / logic of the following snippet, used to calculate the side lengths of a triangle, when all sides are equal to or less than 10 and the total perimeter of the triangle is 24:
[(a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c==24]
The part that is confusing to me is the upper expansion bound on the b and a binding. From what I gather, the ..c and ..b are used to remove additional permutations (combinations?) of the same set of triangle sides.
When I run it with the ..c/b, I get the answer:
[(6,8,10)]
When I don't have the ..c/b:
[(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10], a^2 + b^2 == c^2, a+b+c==24]
as I didn't when I initially typed it in, I got:
[(8,6,10),(6,8,10)]
Which is obviously representative of the same triangle, save for the a and b values have been swapped.
So, can someone walk me through the logic / execution / evaluation of what's going on here?

The original version considers all triplets (a,b,c) where c is a number between 1 and 10, b is a number between 1 and c and a is a number between 1 and b. (6,8,10) fits that criteria, (8,6,10) doesn't (because here a is 8 and b is 6, so a isn't between 0 and 6).
In your version you consider all triplets (a,b,c) where a, b and c are between 1 and 10. You make no restrictions on how a, b and c relate to each other, so (8, 6, 10) is not excluded since all numbers in it are indeed between 1 and 10.
If you think of it in terms of imperative for-loops, your version does this:
for c from 1 to 10:
for b from 1 to 10:
for a from 1 to 10:
if a^2 + b^2 == c^2 and a+b+c==24:
add (a,b,c) to the result
while the original version does this:
for c from 1 to 10:
for b from 1 to c:
for c from 1 to b:
if a^2 + b^2 == c^2 and a+b+c==24:
add (a,b,c) to the result

It's not about execution order. In the first example you don't see the degenerate solution
[(8,6,10)]
since a <= b <= c. In the second case a > b is included in the list comprehension.

List comprehensions can be written in terms of other functions like concatMap, which clarifies the scope of the bindings. As a one-liner, your example becomes something like this:
concatMap (\c -> concatMap (\b -> concatMap (\a -> if a^2 + b^2 == c^2 then (if a+b+c == 24 then [(a,b,c)] else []) else []) (enumFromTo 1 b)) (enumFromTo 1 c)) (enumFromTo 1 10)
Yeah, that looks ugly, but it's similar to what Haskell desugars your comprehensions into. The scope of each of the variables a, b and c, should be obvious from this.
Or alternatively, this can be written with the List monad:
import Control.Monad
example = do c <- [1..10]
b <- [1..c]
a <- [1..b]
guard (a^2 + b^2 == c^2)
guard (a+b+c == 24)
return (a,b,c)
This is actually very similar as the one-liner above, given the definition of the List Monad and guard:
instance Monad [] where
return x = [x]
xs >>= f = concatMap f xs
instance MonadPlus [] where
mzero = []
mconcat = (++)
guard bool = if bool then return () else mzero

Related

Why this Haskell expression won't get a result?

I try to run this in GHCi:
take 100 [ (a,b,c) | a <- [1..], b <- [1..], c <- [1..], a^2 + b^2 == c^2, a<b ]
I would expect it to be calculated because of the lazyness of take, but that's not the case. Why?
You want the list for b to be related to c, and the list for a to be related to b.
The reason for this is a is started at 1, b is starting at 1, and then c is just counting up indefinitely. There are no triangles that have sides 1, 1, x>1.
A solution that should work would be
take 100 [(a,b,c) | c<-[1..], b<-[1..c], a<-[1..b], a^2 + b^2 == c^2]
This solution works because now a will count up from 1 to b, simultaneously, b will count up from 1 to c, and the c just counts up like normal.
It wont't work because you asking to generate triple in the following manner
[(1,1,1),(1,1,4),(1,1,9),(1,1,16),(1,1,25),(1,1,36),(1,1,49),(1,1,64),(1,1,81),(1,1,100),(1,1,121),(1,1,144),(1,1,169),(1,1,196),(1,1,225),(1,1,256),(1,1,289),(1,1,324),(1,1,361),(1,1,400),(1,1,441),(1,1,484),(1,1,529),(1,1,576),(1,1,625),(1,1,676),(1,1,729),(1,1,784),(1,1,841),(1,1,900),(1,1,961),(1,1,1024),(1,1,1089),(1,1,1156),(1,1,1225),(1,1,1296),(1,1,1369),(1,1,1444),(1,1,1521),(1,1,1600),(1,1,1681),(1,1,1764),(1,1,1849),(1,1,1936),(1,1,2025),(1,1,2116),(1,1,2209),(1,1,2304),(1,1,2401),(1,1,2500),(1,1,2601),(1,1,2704),(1,1,2809),(1,1,2916),(1,1,3025),(1,1,3136),(1,1,3249),(1,1,3364),(1,1,3481),(1,1,3600),(1,1,3721),(1,1,3844),(1,1,3969),(1,1,4096),(1,1,4225),(1,1,4356),(1,1,4489),(1,1,4624),(1,1,4761),(1,1,4900),(1,1,5041),(1,1,5184),(1,1,5329),(1,1,5476),(1,1,5625),(1,1,5776),(1,1,5929),(1,1,6084),(1,1,6241),(1,1,6400),(1,1,6561),(1,1,6724),(1,1,6889),(1,1,7056),(1,1,7225),(1,1,7396),(1,1,7569),(1,1,7744),(1,1,7921),(1,1,8100),(1,1,8281),(1,1,8464),(1,1,8649),(1,1,8836),(1,1,9025),(1,1,9216),(1,1,9409),(1,1,9604),(1,1,9801),(1,1,10000),(1,1,10201),(1,1,10404),(1,1,10609),(1,1,10816),(1,1,11025),(1,1,11236),(1,1,11449),(1,1,11664),(1,1,11881),(1,1,12100),(1,1,12321),(1,1,12544),(1,1,12769),(1,1,12996),(1,1,13225),(1,1,13456),(1,1,13689),(1,1,13924),(1,1,14161),(1,1,14400),(1,1,14641),(1,1,14884),(1,1,15129),(1,1,15376),(1,1,15625),(1,1,15876),(1,1,16129),(1,1,16384),(1,1,16641),(1,1,16900),(1,1,17161),(1,1,17424),(1,1,17689),(1,1,17956),(1,1,18225),(1,1,18496),(1,1,18769),(1,1,19044),(1,1,19321),(1,1,19600),(1,1,19881),(1,1,20164),(1,1,20449),(1,1,20736),(1,1,21025),(1,1,21316),(1,1,21609),(1,1,21904),(1,1,22201),(1,1,22500),(1,1,22801),(1,1,23104),(1,1,23409),(1,1,23716),(1,1,24025),(1,1,24336),(1,1,24649),(1,1,24964),(1,1,25281),(1,1,25600),(1,1,25921),(1,1,26244),(1,1,26569),(1,1,26896),(1,1,27225)
There is not bound for C, so haskell clearly never finds 100 triple such that 1^2 +1^2 = c^2.

Having trouble understanding list comprehensions

I've just started learning haskell(literally, tonight!) and I'm having a little trouble understanding the logic of list comprehensions, more specifically the <- operator. A little example on Learn You Some Haskell Finds all tuples that have a length less than 10:
ghci> let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
my initial understanding was that these would all increment together, but after seeing the output I really dont understanding the incrementing method for these lists. Another example that seems to get me is:
ghci> let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]
I would really appreciate a little explanation on these, thanks for your patience with my lack of haskell intelligence.
Read [ as "list of", | as "for", <- as "in", , as "and".
The enumerations are done in nested fashion. [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2] is really
for c from 1 to 10 step 1:
for b from 1 to c step 1:
for a from 1 to b step 1:
if (a^2 + b^2 == c^2):
emit (a,b,c)
In Haskell though, the above is achieved by the following translation
[1..10] >>= (\c-> -- (a function of 'c', producing ...
[1..c] >>= (\b-> -- (a function of 'b', producing ...
[1..b] >>= (\a-> -- (a function of 'a', producing ...
if a^2+b^2==c^2 then [(a,b,c)] else []
-- or: [(a,b,c) | a^2+b^2==c^2]
)))
so you really can see the nested structure here. (>>=) is nothing mysterious too. Read >>= as "fed into" or "pushed through", although its official name is "bind". It is defined (for lists) as
(xs >>= f) = concatMap f xs = concat (map f xs)
f here is called (by map) upon each element of xs, in order. It must produce lists so that they could be combined with concat. Since empty lists [] are eliminated on concat (e.g. concat [[1], [], [3]] == [1,3]) all the elements that do not pass the test are eliminated from the final output.
For the full translation see section 3.11, List Comprehensions, of the Haskell 98 Report. In general a list comprehension may contain a pattern, not just a variable name. The comprehension
[e | pat <- ls, ...]
is translated as
ls >>= (\x -> case x of pat -> [e | ...] ;
_ -> [] )
where pat is some pattern, and x is a fresh variable. When there's a pattern mismatch, an empty list is produced (instead of a run-time error), and that element x of ls is skipped over. This is useful for additional pattern-based filtering, like e.g. [x | Just x <- ls, even x] where all the Nothings in ls are quietly ignored.
[ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ] means, for all combinations of (a,b,c) where a is in [1..10], b is in [1..10], c is in [1..10]
If you want the (1,1,1) (2,2,2) kinds, you should use zip: zip [1..10] [1..10] or for 3 lists, zip3 [1..10] [1..10] [1..10]
I think of list comprehension syntax as Haskell's attempt to get Set-builder notation in the language. We use '[' rather than '{' and '<-' rather than '∈'. List comprehension syntax can even be generalized to arbitrary monads.

How are dependent ranges computed in a list comprehension?

I'm currently making my way through Learn You a Haskell for Great Good!, and I'm confused on the penultimate example in Chapter 2.
As a way of generating triples representing all right triangles with all sides that are whole numbers less than or equal to 10, he gives this definition:
rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]
What I'm specifically confused about is the fact that b is bound to a list that ranges from 1 to c, and similarly with a. If my understanding is correct, c will be evaluated to all values in the list it is bound to, but I still don't see which value is being used for c in the range (e.g. all values of c, only the first c, etc.)
If it's not too much, a step by step explanation of how this evaluates would be great. :)
Thanks in advance!
Let's consider two simpler list comprehensions:
ex1 = [(a,b) | a <- [1..3], b <- [1..3]]
ex2 = [(a,b) | a <- [1..3], b <- [1..a]]
They're almost the same, but in the second case, b ranges from 1 to a, not 1 to 3. Let's consider what they're equal to; I've formatted their values in such a way as to make a point.
ex1 = [ (1,1), (1,2), (1,3)
, (2,1), (2,2), (2,3)
, (3,1), (3,2), (3,3) ]
ex2 = [ (1,1),
, (2,1), (2,2),
, (3,1), (3,2), (3,3) ]
In the first example, the list comprehension draws every possible combination of elements from [1..3] and [1..3]. But since we're talking about lists, not sets, the order it does that in is important. Thus, in more detail, what ex1 really means is this:
Let a be equal to every possible value from its list.
For each value of a, let b be every possible value from its list.
(a,b) is an element of the output list
Or, rephrased: "for every possible value of a, compute (a,b) for every possible value of b." If you look at the order of the results, this is what happens:
For the first three elements, a is equal to 1, and we see it paired with every value of b.
For the next three elements, a is equal to 2, and we see every value of b.
And finally, for the last three elements, a is equal to 3 and we see every value of b.
In the second case, much the same thing happens. But because a is picked first, b can depend on it. Thus:
First, a is equal to 1, and we see it paired with every possible value of b. Since b <- [1..a], that means b <- [1..1], and so there's only one option.
After one element, then, a is equal to 2, and we see that paired with every possible value of b. Now that means b <- [1..2], and so we get two results.
Finally, a is equal to 3, and so we're picking b <- [1..3]; this gives us the full set of three results.
In other words, because the list comprehensions rely on an ordering, you can take advantage of that. One way to see that is to imagine translating these list comprehensions into nested list comprehensions:
ex1 = concat [ [(a,b) | b <- [1..3]] | a <- [1..3] ]
ex2 = concat [ [(a,b) | b <- [1..a]] | a <- [1..3] ]
To get the right behavior, a <- [1..3] must go on the outside; this ensures that the bs change faster than the as. And it hopefully makes it clear how b can depend on a. Another translation (basically the one used in the Haskell 2010 Report) would be:
ex1 = concatMap (\a -> [(a,b) | b <- [1..3]]) [1..3]
= concatMap (\a -> concatMap (\b -> [(a,b)]) [1..3]) [1..3]
ex2 = concatMap (\a -> [(a,b) | b <- [1..a]]) [1..3]
= concatMap (\a -> concatMap (\b -> [(a,b)]) [1..a]) [1..3]
Again, this makes the nesting very explicit, even if it's hard to follow. Something to keep in mind is that if the selection of a is to happen first, it must be on the outside of the translated expression, even though it's on the inside of the list comprehension. The full, formal translation of rightTriangles would then be
rightTriangles =
concatMap (\c ->
concatMap (\b ->
concatMap (\a ->
if a^2 + b^2 == c^2
then [(a,b,c)]
else []
) [1..b]
) [1..c]
) [1..10]
As a side note, another way to write rightTriangles is as follows:
import Control.Monad (guard)
rightTriangles = do c <- [1..10]
b <- [1..c]
a <- [1..b]
guard $ a^2 + b^2 == c^2
return (a,b,c)
You probably haven't used do notation yet, and certainly not for anything but IO, so I'm not saying you should necessarily understand this. But you can read the x <- list lines as saying "for each x in list", and so read this as a nested loop:
rightTriangles = do
c <- [1..10] -- For each `c` from `1` to `10`, ...
b <- [1..c] -- For each `b` from `1` to `c`, ...
a <- [1..b] -- For each `a` from `1` to `b`, ...
guard $ a^2 + b^2 == c^2 -- If `a^2 + b^2 /= c^2`, then `continue` (as in C);
return (a,b,c) -- `(a,b,c)` is the next element of the output list.
Note that the continue only skips to the next iteration of the innermost loop in this interpretation. You could also write it as
rightTriangles = do c <- [1..10]
b <- [1..c]
a <- [1..b]
if a^2 + b^2 == c^2
then return (a,b,c)
else [] -- or `mzero`
Where the last lines say "if a^2 + b^2 == c^2, add (a,b,c) to the output list; otherwise, add nothing." I only mention this because I thought seeing it written this way might help make the "nested loop"-type structure that's going on clear, not because you should fully understand do-notation while reading Chapter 2 of Learn You A Haskell :-)
Seeing you have experience with imperative programming, a short answer would be: similar to this for nesting (pseudo code):
for(c = 1; c <= 10; c++) {
for(b = 1; b <= c; b++) {
for(a = 1; a <= b; a++) {
if(a ^ 2 + b ^ 2 == c ^ 2) {
list.append((a, b, c));
}
}
}
}

Pythagorean triple in Haskell without symmetrical solutions

I gotta do the Pythagorean triple in Haskell without symmetrical solutions. My try is:
terna :: Int -> [(Int,Int,Int)]
terna x = [(a,b,c)|a<-[1..x], b<-[1..x], c<-[1..x], (a^2)+(b^2) == (c^2)]
and I get as a result:
Main> terna 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]
As you can see, I´m getting symmetrical solutions like: (3,4,5) (4,3,5). I need to get rid of them but I don´t know how. Can anyone help me?
Every time you have a duplicate you have one version in which a is greater than b and one where b is greater than a. So if you want to make sure you only ever get one of them, you just need to make sure that either a is always equal to or less than b or vice versa.
One way to achieve this would be to add it as a condition to the list comprehension.
Another, more efficient way, would be to change b's generator to b <- [1..a], so it only generates values for b which are smaller or equal to a.
Speaking of efficiency: There is no need to iterate over c at all. Once you have values for a and b, you could simply calculate (a^2)+(b^2) and check whether it has a natural square root.
Don't know Haskell at all (perhaps you're learning it now?) but it seems like you could get rid of them if you could take only the ones for which a is less than or equal to b. That would get rid of the duplicates.
Try with a simple recursive generator:
http://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples
(new article)
http://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
EDIT (7 May 2014)
Here I have made infinite generator that can generate primitive triplets ordered by perimeter (but can be modified to be ordered by other parameter - hypotenuses, area, ...) as long as it holds that any triplet is smaller that any generated from generator matrix according to provided compare function
import Data.List -- for mmult
merge f x [] = x
merge f [] y = y
merge f (x:xs) (y:ys)
| f x y = x : merge f xs (y:ys)
| otherwise = y : merge f (x:xs) ys
mmult :: Num a => [[a]] -> [[a]] -> [[a]]
mmult a b = [ [ sum $ zipWith (*) ar bc | bc <- (transpose b) ] | ar <- a ]
tpgen_matrix = [[[ 1,-2, 2],[ 2 ,-1, 2],[ 2,-2, 3]],
[[ 1, 2, 2],[ 2 , 1, 2],[ 2, 2, 3]],
[[-1, 2, 2],[-2 , 1, 2],[-2, 2, 3]]]
matrixsum = sum . map sum
tripletsorter x y = ( matrixsum x ) < ( matrixsum y ) -- compare perimeter
triplegen_helper b = foldl1
( merge tripletsorter )
[ h : triplegen_helper h | x <- tpgen_matrix , let h = mmult x b ]
triplets = x : triplegen_helper x where x = [[3],[4],[5]]
main = mapM print $ take 10 triplets
You can do the following:
pythagorean = [ (x,y,m*m+n*n) |
m <- [2..],
n <- [1 .. m-1],
let x = m*m-n*n,
let y = 2*m*n ]
This might work: Got it from this tutorial
triangles x = [(a,b,c) | c <- [1..x], b <- [1..c], a <- [1..b] , a^2 + b^2 == c^2]
List comprehension syntax makes this easy:
triplets :: Integer -> [(Integer, Integer, Integer)]
triplets d = [(a,b,c) | a <- [1..d], b <- [a..d], c <- [b..d], a^2 + b^2 == c^2]
This basically says than we build a list from as,bs and cs, where a changes from 1 to d, b changes from current a to d and etc. It also says that a^2 + b^2 == c^2 should hold.

Haskell recursive list comprehension causes C Stack Overflow

So I'm making a list of prime numbers to help me learn haskell using simple trial division (no fancy stuff until I get better with the language). I'm trying to use the following code:
primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
This is loaded without an error. However:
>take 2 primes
[2ERROR - C stack overflow
I tried the same thing with nested list comprehensions. It doesn't work. I would guess that I'm making too many recursive calls, but this shouldn't be the case if i'm only computing one prime. In my mind the lazy evaluation should make it so that take 2 primes does something along the lines of:
primes = 2 : [ 3 | all (\p -> (mod 3 p) /= 0) [2] ]
Which doesn't require all that much computation - mod 3 2 == True, so all (\p -> (mod 3 p) /= 0) == True, which means take 2 primes == [2, 3], right? I don't understand why this isn't working. Hopefully someone much more versed in the black magic of functional programming can help me...
This is on HUGS, if that makes any difference.
EDIT- I was able to come up with this solution (not pretty):
primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) (takeWhile (<= (ceiling (sqrt (fromIntegral x)))) primes)]
EDIT2- The program works fine when interpreted through HUGS or GHCi, but when I try to compile it with GHC, it outputs test: <<loop>>. Anybody know what the problem is?
Hugs shouldn't do this, but the code is broken anyway so it doesn't matter. Consider:
primes = 2 : [ x | x <- [3..], all (\p -> (mod x p) /= 0) primes]
How do you determine if 3 is prime? well, does mod 3 2 == 0? No. Does mod 3 ??? == 0? OOPS! What is the next element of primes after two? we don't know, we are trying to compute it. You need to add an ordering constraint that adds 3 (or any other x) once all p elem primes less than sqrt x have been tested.
The documentation for all says "For the result to be True, the list must be finite"
http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:all
The previous answers explained why the original comprehension didn't work, but not how to write one that would work.
Here is a list comprehension that recursively, lazily (albeit not efficiently) computes all primes:
let primes = [x | x <- 2:[3,5..], x == 2 || not (contains (\p -> 0 == (mod x p)) (takeWhile (\b -> (b * b) < x) primes))]
Obviously we don't need to check mod x p for all primes, we only need to do it for primes less than the sqrt of the potential prime. That's what the takeWhile is for. Forgive the (\b -> (b * b) < x) this should be equivalent to (< sqrt x) but the Haskell type system didn't like that.
The x == 2 prevents the takeWhile from executing at all before we've added any elements to the list.

Resources