vijaicv
vijaicv

Reputation: 555

return type of (fmap.fmap) func vs fmap (fmap func)

following is the sample code I am testing

import Control.Exception

safeLoad :: FilePath -> IO (Either IOException String)
safeLoad f = (Right <$> readFile f) `catch` (pure . Left)

fileChars :: FilePath -> IO (Either IOException Int)
fileChars = fmap (fmap length) . safeLoad

fileChars' :: FilePath -> IO Int
fileChars' = (fmap.fmap) length safeLoad

example :: [Maybe Integer]
example = (fmap.fmap) (+1) [Just 2,Just 3]

here the type of (fmap.fmap) evaluates as:

ghci> :t ((fmap.fmap) length)
((fmap.fmap) length)
  :: (Functor f1, Functor f2, Foldable t) =>
     f1 (f2 (t a)) -> f1 (f2 Int)

the type of (fmap (fmap ...)) also is:

ghci> :t (fmap (fmap length))
(fmap (fmap length))
  :: (Functor f1, Functor f2, Foldable t) =>
     f1 (f2 (t a)) -> f1 (f2 Int)

but why does fileChars' return IO Int while fileChars return IO (Either IOException Int)?

Upvotes: 2

Views: 78

Answers (1)

Will Ness
Will Ness

Reputation: 71074

Because

fileChars' = (fmap.fmap) length safeLoad
           = fmap (fmap length) safeLoad

while

fileChars = fmap (fmap length) . safeLoad

Mind the dot. The two expressions are not equivalent.

Upvotes: 6

Related Questions