Good day,
I am new to haskell and having a hell of a time trying to compile the following function definition in haskell
chaseFile :: [FilePath] -- ^ path (directories to search)
-> String -- ^ base name
-> [String] -- ^ possible extensions
-> IO String -- ^ contents of file
chaseFile dirs basename exts
= do results <- mapM tryReadFile fnames
case dropWhile hasFailed results of
((Right (fc,fn)):_)
-> errLn ("Read file: "++fn) >> return fc
_ -> errLn ("Could not find file: "++basename) >> mzero
where
fnames = [d++'/':basename++'.':e | d <- dirs, e <- exts]
hasFailed (Left _) = True
hasFailed _ = False
tryReadFile fn = try ( readFile fn >>= \fc -> return (fc,fn) )
the compiler gives the following error
*** Parser:
*** Renamer/typechecker:
..\contrib\StrategyLib-5.0\library\ChaseImports.hs:103:24:
Not in scope: `try'
Thanks in anticipation
I added
import Control.Exception (try)
and I got the following compiler errors
*** Parser:
*** Renamer/typechecker:
..\contrib\StrategyLib-5.0\library\ChaseImports.hs:96:24:
No instance for (Exception t0) arising from a use of `tryReadFile'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Exception Data.Dynamic.Dynamic
-- Defined in `Data.Dynamic'
instance Exception ArithException -- Defined in `GHC.Exception'
instance Exception ErrorCall -- Defined in `GHC.Exception'
...plus 8 others
In the first argument of `mapM', namely `tryReadFile'
In a stmt of a 'do' block: results <- mapM tryReadFile fnames
In the expression:
do { results <- mapM tryReadFile fnames;
case dropWhile hasFailed results of {
((Right (fc, fn)) : _) -> errLn ("Read file: " ++ fn) >> return fc
_ -> errLn ("Could not find file: " ++ basename) >> mzero } }
The file is part of the XsdMetz project (svn checkout xsdmetz.googlecode.com/svn/trunk xsdmetz-read-only) written before 2010. Could it be that it is not haskel 2010 compliant?
Given your error message Not in scope: `try'
I'm guessing the layout discussion is all a misunderstanding, and you've rather forgot to import that function, which is not in the Prelude
. Put at the top of your file something like
import Control.Exception (try)
EDIT: It turns out that the code assumes the old Haskell 98 / Haskell 2010 semantics for try
. Unfortunately modern GHC has hidden that away in the haskell98
and haskell2010
packages. It is possible you should use one of those anyway, if you need to compile the whole XsdMetz project. But otherwise, a simpler workaround is to do
import System.IO.Error (tryIOError)
and substitute tryIOError
in your code instead of try
.
Alternatively, you can use Control.Exception.try
, but then you need to put a type annotation somewhere to restrict its highly overloaded type so it knows what type of exception to catch.