reset password
Author Message
rabbott
Posts: 1649
Posted 20:59 Sep 07, 2016 |

Recall that we defined goldbachPairs as follows.

goldbachPairs g = [(p, k) | k <- takeWhile ((< g) . (*2) . (^2)) [1 .. ],  
                            p <- [g - 2 * k * k], isPrime p] 

 

Let's define a predicate satisfiesGoldbach as follows.

satisfiesGoldbach g = not (null (goldbachPairs g))

So, for example,

> goldbachPairs 101
[(83,3),(29,6),(3,7)]

and

> satisfiesGoldbach 101
True

 

My question is: how many of the Goldbach pairs are computed before satisfiesGoldbach returns True?

 

Here's a tool you can use to help you find out.

At the start of the file add the line

import Debug.Trace -- See https://hackage.haskell.org/package/base-4.9.0.0/docs/Debug-Trace.html

Then modify goldbachPairs as follows

goldbachPairs g = [(p, k) | k <- takeWhile ((< g) . (*2) . (^2)) [1 .. ], trace ("k = " ++ show k) True, 
                            p <- [g - 2 * k * k], isPrime p, trace ("Returning " ++ show (p, k)) True

 

(The function show in Haskell is like toString in Java. It doesn't do output. It just converts its argument to a String. We must call it to do String concatenation (++).)

Run both goldbachPairs 101 and satisfiesGoldbach 101.

What's the difference in the trace output? Can you explain why. What does this have to do with Haskell being lazy?

Most importantly: how does Haskell manage to do what you see?

Last edited by rabbott at 21:30 Sep 08, 2016.