Skip to content

Instantly share code, notes, and snippets.

@wrschneider
Created February 7, 2016 15:24
Show Gist options
  • Save wrschneider/fdb0ccefc5c68ccdf9a4 to your computer and use it in GitHub Desktop.
Save wrschneider/fdb0ccefc5c68ccdf9a4 to your computer and use it in GitHub Desktop.
wrap text with maximum number of chars per line
wordWrap :: String -> Int -> String
wordWrap "" _ = ""
wordWrap str limit =
let
helper [] result curLineLen = result
helper (curWord:remainder) result curLineLen
| ((length curWord) + curLineLen >= limit) = helper remainder (result ++ "\n" ++ curWord) (length curWord)
| otherwise = helper remainder (result ++ " " ++ curWord) (curLineLen + 1 + length curWord)
wordList = words str
firstWord = wordList!!0
in helper (drop 1 wordList) firstWord (length firstWord)
@jszmajda
Copy link

jszmajda commented Feb 8, 2016

Cool stuff, let's see:

First off I think this approach is great, it looks quite efficient and reads well :)

Haskellers love to declare types on functions, so that would push you to pull the helper function out into its own top-level function with a type signature, like helper :: [String] -> String -> Int -> String. Looking at these type signatures and seeing how they line up is a very helpful part of Haskell. In fact, if you look at more Haskell code you'll see a lot of things like newtype UnprocessedList = [String] to 'alias' types for readability (you'd then write something like ... helper :: UnprocessedList -> ResultAccumulator -> CurrentLineLength -> Result to help you consider what you're working on).
FYI you do lose the local data bindings (e.g. access to str), but generally that's considered a good thing---the less context a function has to work with, or rather the more defined the context is that a function has to work with, the more bug-free and maintainable it will be.

Small thing, but it's more Haskell style to put spaces around operators, so on line 11: firstWord = wordList !! 0, or even more stylistically: firstWord = head wordList

An interesting addition would be to take the pattern you have in (result ++ "\n" ++ curWord) and (result ++ " " ++ curWord) and extract another function, something with a type signature like :: String -> String -> String -> String. BTW, there are some really great searches you can do in the Haskell world with type signatures, check out what you get when you search that signature on Hayoo: http://hayoo.fh-wedel.de/?query=String+-%3E+String+-%3E+String+-%3E+String

Finally, if you want to learn more Haskell, I strongly recommend trying out exercism.io. It's a community site built around micro-code-reviews like this, I think you'll like it :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment