Search code examples
haskellbindmonadscomposite

Binding monads into composites (Haskell)


Good day folks. I'm seeking some clarifications on monads please and using bind (while going into a composite .) please.

So for this example:

--Monadic parts:
readFile :: String -> IO File
putStr :: String -> IO()
-- Non monadic parts
toMatrix :: String -> CustomMatrix
toString :: CustomMatrix -> String

Essentially I'm lazily reading a file (readFile) then producing a custom matrix, converting the matrix to a string output. Then returning.

fileReading :: String -> IO
fileReading file = putStr(toString . toMatrix . readFile file)

This is when I start creating a mess by using bind >>= to go from readFile file. Is there a way I can continue to use composites . and bind and compose without making an unreadable mess (not really my aim).

As always, any help is gratefully received. Thanks folks.


Solution

  • You can't get away without using some monadic function (like >>=) in this example. You can't use normal function composition with IO values if you actually want to end up doing some IO.

    Happily, you can still write the code fairly readably:

    fileReading file = readFile file >>= putStr . toString . toMatrix
    

    This works because the two . operations combine two non-IO functions with a final IO function. At that point, you have two IO values: an IO String and a String -> IO () function (the entire putStr . toString . toMatrix expression has that type). This is exactly what >>= takes, so you're all set.

    If you want the code to have the same order as above, you can use the backwards bind operator:

    fileReading file = putStr . toString . toMatrix =<< readFile file
    

    Some people find this version more readable because all of the code "flows" in the same direction.