I have just started reading through Learn you a Haskell I got up to list comprehension and started to play around in GHCi, my aim was to make a times table function that takes a number n and an upper limit upperLimit and return a nested list of all the 'tables' up to n for example

> timesTable 2 12

the actual function/list comprehension I came up with is

> let timesTable n upperLimit = [[(n-y) * x | x <- [1..upperLimit]] | y <- reverse [0..(n-1)]]

Any feedback on the above would be greatly appreciated as this is the first time I have really used a functional language, so if there is a better way or something I have missed please let me know.

  • \$\begingroup\$ Note that reverse [0..(n-1)] (even though it isn't needed, as Nicolas' answer shows) could be written [(n-1),(n-2)..0]. \$\endgroup\$
    – Landei
    Commented Jan 29, 2012 at 17:06

2 Answers 2


Your function could be simplified a little, and I find it helpful to define functions using declarations, since type signatures are really helpful (although admittedly your example is simple enough that it doesn't matter):

timesTable :: Int -> Int -> [[Int]]
timesTable n u = [[y * x | x <- [1 .. u]] | y <- [1 .. n]]

The key thing I noticed was that you were using n-y: it should be obvious that this part of the expression becomes the following values in each iteration of y: [n-(n-1), n-(n-2), ... n-0], which is just [1 .. n].

  • \$\begingroup\$ Thanks, I had a feeling that there was something fishy and convoluted with what I had done, feeling a bit silly now because it is very obvious, am just reading the Types and Type Classes chapter which covers declarations, cheers \$\endgroup\$
    – T I
    Commented Jan 29, 2012 at 15:37
  • \$\begingroup\$ We all have silly moments :-) I'm glad I could help! \$\endgroup\$
    – Nicolas Wu
    Commented Jan 30, 2012 at 2:18
  • \$\begingroup\$ Is there a specific reason you chose Int rather than Integer or a polymorphic type? \$\endgroup\$
    – sepp2k
    Commented Feb 9, 2012 at 23:57
  • \$\begingroup\$ Oh, not really. You'd choose Int over Integer if you were interested in efficiency, and your numbers aren't too big. You'd choose Integer for unbounded precision, and you'd use a Num class constraint if you wanted to stay flexible (at the cost of having to pass a dictionary around). \$\endgroup\$
    – Nicolas Wu
    Commented Feb 10, 2012 at 18:46

We need no stinkin' list comprehensions. And multiplication is overrated as well...

timesTable n = scanl1 (zipWith (+)) . replicate n . enumFromTo 1     

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.