1
votes

I am trying to do a little error handling when opening a file, to be sure that the file exists/is readable. Here's my attempt :

init struct = do
    str <- try $ readFile (filePath struct)
    case str of
        Left exception -> print exception
        Right content -> execute content struct

(Struct is a data structure where I keep my file path and other variables). I get this error:

Ambiguous type variable ‘a0’ arising from a use of ‘try’ prevents the constraint ‘(Exception a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be.

But I just don't understand how to fix it.

1

1 Answers

8
votes

it's because the result of try :: ... -> IO (Either e a) has a type-parameter for the exception e and you just put this into print which can handle all sort of stuff (as long as the e is in Show) - so it's not obvious to the compiler what type the intermediate e needs to be.

This is very similar to show . read - that should have type String -> String but what is read supposed to do? Read a Int, a Float - something different?


Easiest way to fix this is IMO with an type-application:

{-# LANGUAGE TypeApplications #-}

init struct = do
    str <- try @IOException $ readFile (filePath struct)
    case str of
        Left exception -> print exception
        Right content -> execute content struct

Of course you can add the type annotation wherever you want:

str <- try $ readFile (filePath struct) :: IO (Either IOException MyStruct)

etc.