I'm learning Haskell on my own and I'm following the material of a course.
I would like to know if this is idiomatic Haskell.
asList :: [String] -> String
asList ss = "[" ++ (concat $ intersperse "," ss) ++ "]"
2 Answers 2
It looks idiomatic to me.
There's one slight improvement to the code that I could come up with. There is a function that does what you're doing in the middle, called intercalate
. Here's the definition, from Data.List:
intercalate :: [a] -> [[a]] -> [a]
intercalate xs xss = concat (intersperse xs xss)
Using that, your function becomes:
asList :: [String] -> String
asList ss = "[" ++ (intercalate "," ss) ++ "]"
-
\$\begingroup\$ Beautiful! When I wrote asList, I actually remember seeing intercalate - but did not take the mental leap to consider a a Char. (I considered a as String, in which case it is not as useful). \$\endgroup\$j-a– j-a2014年11月21日 05:24:37 +00:00Commented Nov 21, 2014 at 5:24
-
\$\begingroup\$ Perhaps - you could include the performance comparison in your answer? It is interesting/useful enough not to be hidden in a comment. \$\endgroup\$j-a– j-a2014年11月21日 05:29:17 +00:00Commented Nov 21, 2014 at 5:29
The ++
operator should be used sparingly, and especially avoided after long lists. In this case, the ++ "]"
at the end would require walking down nearly the entire constructed string to append the final character.
Here is an implementation that avoids that problem:
asList :: [String] -> String
asList ss = '[' : asList' ss
where
asList' (a:b:ss) = a ++ (',' : asList' (b:ss))
asList' (a:ss) = a ++ asList' (ss)
asList' [] = "]"
-
\$\begingroup\$ OK I see, thanks. To me, this is sacrificing readability for performance - is it common to go to this extent to avoid ++ operator? Or is that only done for performance-critical functions? \$\endgroup\$j-a– j-a2014年11月20日 18:21:51 +00:00Commented Nov 20, 2014 at 18:21
-
1\$\begingroup\$ This was also interesting: stackoverflow.com/questions/5188286/… \$\endgroup\$j-a– j-a2014年11月20日 18:24:42 +00:00Commented Nov 20, 2014 at 18:24
-
\$\begingroup\$ I agree that your original code is more readable. In the end, it's up to you to decide whether readability or performance is more important. \$\endgroup\$200_success– 200_success2014年11月20日 18:26:49 +00:00Commented Nov 20, 2014 at 18:26
-
2\$\begingroup\$ I tried this with
replicate 50000000 "abc"
as input, and on my machine in GHCI using:set +s
, the OP's code runs in about 3.5 seconds, and your code runs in about 35 seconds. I tried writing a bit of code that usedfoldr (:)
to avoid the++
at the end, assuming it would be faster. My code ran in about 4.2 seconds. \$\endgroup\$Michael Shaw– Michael Shaw2014年11月20日 21:12:42 +00:00Commented Nov 20, 2014 at 21:12
insertBST
, you should probably include the correspondingsearchBST
function in that question too. \$\endgroup\$