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.
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– T I2012年01月29日 15:37:10 +00:00Commented Jan 29, 2012 at 15:37
-
\$\begingroup\$ We all have silly moments :-) I'm glad I could help! \$\endgroup\$Nicolas Wu– Nicolas Wu2012年01月30日 02:18:20 +00:00Commented Jan 30, 2012 at 2:18
-
\$\begingroup\$ Is there a specific reason you chose
Int
rather thanInteger
or a polymorphic type? \$\endgroup\$sepp2k– sepp2k2012年02月09日 23:57:21 +00:00Commented 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– Nicolas Wu2012年02月10日 18:46:54 +00:00Commented 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
reverse [0..(n-1)]
(even though it isn't needed, as Nicolas' answer shows) could be written[(n-1),(n-2)..0]
. \$\endgroup\$