3

How do I write the following function without using the "do" notation?

wordsCount =  do 
    putStr "Write a line and press [enter]:\n"
    s <- getLine
    putStr $ show $ length . words $ s
    putChar '\n'
Kritzefitz
  • 2,644
  • 1
  • 20
  • 35
John Doe
  • 191
  • 2
  • 15
  • 1
    These two questions ([1](http://stackoverflow.com/q/16964732/2211273), [2](http://stackoverflow.com/q/25255260/2211273)) questions also are about desugaring do syntax. [This answer](http://stackoverflow.com/a/16726740/2211273) also explains nicely how to do it. – Kritzefitz Jun 06 '16 at 17:05

1 Answers1

3

Instead of using do, you can use >> and >>=:

wordsCount = putStr "Write a line and press [enter]:\n" >> getLine >>= putStr . show . length . words >> putChar '\n'

Or making it easier to read:

wordsCount = putStr "Write a line and press [enter]:\n" >>
    getLine >>=
    putStr . show . length . words >>
    putChar '\n'

A more straight-forward translation would be:

wordsCount = putStr "Write a line and press [enter]:\n" >>
    getLine >>=
    \s -> (putStr $ show $ length $ words s) >>
    putChar '\n'

Basically the compiler converts such do-notation blocks to its monadic equivalent (using only >> and >>=). do is only syntactical sugar such that one does not have to write >>= each time and/or mange variables.

Additional notes:

  • as @ChadGilbert said in his comment, the parenthesis should be wrapped around the function, excluding the \s -> such that the s can be used later on in the program, for example:

    -- This is not an equivalent program
    wordsCount = putStr "Write a line and press [enter]:\n" >>
        getLine >>=
        \s -> (putStr $ show $ length $ words s) >>
        putChar '\n' >>
        putStrLn s -- repeat s
    
  • Instead of using putStr and putChar, you can use putStrLn. For example:

    wordsCount = putStr "Write a line and press [enter]:\n" >>
        getLine >>=
        putStrLn . show . length . words
    
Community
  • 1
  • 1
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • In your more straight-forward translation, shouldn't the parentheses be wrapping simply the `putStr $ show $ length $ words s` statement? Wrapping `(\s -> putStr $ show $ length $ words s)` means that `s` is not usable in subsequent monadic statements – Chad Gilbert Jun 06 '16 at 17:07
  • @ChadGilbert: you mean like the updated answer? Yes indeed. Thanks for spotting that. – Willem Van Onsem Jun 06 '16 at 17:12
  • 1
    @ChadGilbert: I've updated the answer with an additional note to further explain the isue, many thanks. – Willem Van Onsem Jun 06 '16 at 17:20