I am playing with some online examples, and one has this phrase:
do ... contents <- getDirectoryContents path `catch` const (return [])
But it won't compile for me, and gives the error:
No instance for (Exception e0) arising from a use of `catch'
The type variable `e0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Exception NestedAtomically
-- Defined in `Control.Exception.Base'
instance Exception NoMethodError
-- Defined in `Control.Exception.Base'
instance Exception NonTermination
-- Defined in `Control.Exception.Base'
...plus 7 others
In a stmt of a 'do' block:
contents <- getDirectoryContents path `catch` const (return [])
In the expression:
do { contents <- getDirectoryContents path
`catch` const (return []);
I had to change it to give a type for the handler, which is OK now but a bit messier:
contents <- getDirectoryContents path `catch` (\(SomeException e) -> const (return []) e)
So I am wondering why I needed to make this change, and if this is the most concise way to do it. (Yes, I know I could use alternate forms of try, handle, ...)
catch
has type Exception e => IO a -> (e -> IO a) -> IO a
so (e -> IO a)
is where you are passing the const
function result but the const
return type in this case is (e0 -> IO [])
. As you can see that this type has e0
which is not constrained like it was required in catch i.e e
should have Exception
instance and thats what the error says.
So conceptually, you are passing something that is "less constrained" to a place where something "more constrained" is required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With