Search code examples
haskellmonadspointfree

Point free version for readMaybe


I want to write a function to read an Int without do notation. It works (see below), but I was wondering if it the bit around readMaybe can be written in point free form (or cleaned up a bit in some other way)?

main :: IO ()
main = getLine >>= (\x -> return $ (readMaybe x :: Maybe Int)) >>= print 

Solution

  • Step 1: Replace the lambda with its pointfree equivalent:

    main :: IO ()
    main = getLine >>= return . (readMaybe :: String -> Maybe Int) >>= print
    

    Step 2: Replace m >>= return . f with f <$> m:

    main :: IO ()
    main = (readMaybe :: String -> Maybe Int) <$> getLine >>= print
    

    Step 3: Replace f <$> m >>= g with m >>= g . f:

    main :: IO ()
    main = getLine >>= print . (readMaybe :: String -> Maybe Int)
    

    Step 4: Use a type application instead of writing out a long, awkward type:

    {-# LANGUAGE TypeApplications #-}
    
    main :: IO ()
    main = getLine >>= print . readMaybe @Int
    

    As an alternative to using <$> in steps 2 and 3, you can accomplish the same with just the monad laws, like this (picking up after step 1):

    Replace m >>= f >>= g with m >>= \x -> f x >>= g (associativity):

    main :: IO ()
    main = getLine >>= \x -> (return . (readMaybe :: String -> Maybe Int)) x >>= print
    

    Simplify the . away:

    main :: IO ()
    main = getLine >>= \x -> return ((readMaybe :: String -> Maybe Int) x) >>= print
    

    Replace return x >>= f with f x (left identity):

    main :: IO ()
    main = getLine >>= \x -> print ((readMaybe :: String -> Maybe Int) x)
    

    Now just replace that new lambda with its pointfree equivalent, and you end up in the exact same place as step 3.