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)
?
CodePudding user response:
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.