4
\$\begingroup\$

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
[[1,2..12],[2,4..24]]

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.

\$\endgroup\$
  • \$\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 Jan 29 '12 at 17:06
5
\$\begingroup\$

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].

\$\endgroup\$
  • \$\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 Jan 29 '12 at 15:37
  • \$\begingroup\$ We all have silly moments :-) I'm glad I could help! \$\endgroup\$ – Nicolas Wu Jan 30 '12 at 2:18
  • \$\begingroup\$ Is there a specific reason you chose Int rather than Integer or a polymorphic type? \$\endgroup\$ – sepp2k Feb 9 '12 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 Feb 10 '12 at 18:46
1
\$\begingroup\$

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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