Reputation: 191
I have a function "management" that checks parameters and return a Maybe (String):
My problem arrived when I get a file and check if this file exists.
Couldn't match expected type ‘Maybe String’ with actual type ‘IO (Either e0 a2)’
managagment :: [String] -> Maybe (String)
managagment [] = Nothing
managagment ["-h"] = Just (help)
managagment [file] = try $ readFile file >>= \result -> case result of
Left e -> Nothing
Right content -> Just (content)
Upvotes: 0
Views: 810
Reputation: 64740
There are several problems
Function application ($
) is lower precedence than bind (>>=
)
You said:
try $ readFile file >>= \res...
Which means
try ( readFile file >>= \res... )
But you wanted:
try ( readFile file ) >>= \res...
IO (Maybe a)
and Maybe a
are distinct
You have a function using IO (via readFile
and try
) but many of the cases do not return an IO result (Nothing
and Just content
).
Solution: Return via return Nothing
or pure Nothing
to lift a value into the IO monad.
The exception type was ambiguous
The try
function can catch any exception type, just look at the signature:
try :: Exception e => IO a -> IO (Either e a)
When you totally ignore the exception you leave the type checker with no information to decide what e
should be. In these situations an explicit type signature is useful, such as:
Left (e::SomeException) -> pure Nothing
managagment
is partial
managagment ["a","b"]
is undefined as is any input list of length over one. Consider a final equational definition of:
managagment _ = managagment ["-h"]
Or more directly:
managagment _ = pure $ Just help
Style and other notes
managagment
should probably management
Just (foo)
is generally Just foo
help
is not a function that returns a String. It is a value of type String.help
.Fixed Code
Consider instead:
#!/usr/bin/env cabal
{- cabal:
build-depends: base
-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase #-}
import Control.Exception (try, SomeException)
main :: IO ()
main = print =<< management []
help :: String
help = "so helpful"
management :: [String] -> IO (Maybe String)
management [] = pure Nothing
management ["-h"] = pure $ Just help
management [file] =
try (readFile file) >>=
\case
Left (e::SomeException) -> pure Nothing
Right content -> pure $ Just content
management _ = pure $ Just help
And test as such:
% chmod +x x.hs
% ./x.hs
Upvotes: 1