美好的一天,
我是haskell的新手,并且有一段时间试图在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) )
编译器出现以下错误
*** Parser:
*** Renamer/typechecker:
..\contrib\StrategyLib-5.0\library\ChaseImports.hs:103:24:
Not in scope: `try'
感谢您的期待
我添加了
import Control.Exception (try)
我得到了以下编译器错误
*** 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 } }
该文件是2010年之前编写的XsdMetz项目(svn checkout xsdmetz.googlecode.com/svn/trunk xsdmetz-read-only)的一部分。可能是因为它不符合haskel 2010吗?
答案 0 :(得分:3)
布局失败。
您的where子句应该比函数名称缩进。 (where子句中的所有绑定必须具有相同的对齐方式;您这样做了。)
do中的所有语句应该具有相同的对齐方式,并且它们应该缩进多于where。 (“结果”和“案例”应该从同一列开始。)
案例中的所有模式应该具有相同的对齐方式,并且它们应该比do语句缩进更多。 (“((右”和“_”应从同一列开始)
如果你不喜欢空白区域的敏感度,你可以通过提供明确的大括号和分号来(有效地)选择退出布局规则。
答案 1 :(得分:2)
where子句必须在函数名称的一个级别中标记。
答案 2 :(得分:2)
鉴于您的错误消息Not in scope: `try'
我猜测布局讨论是一个误解,而您宁愿忘记导入该功能,而不是Prelude
。在文件的顶部放置类似
import Control.Exception (try)
编辑:事实证明,代码假定try
的旧Haskell 98 / Haskell 2010语义。不幸的是,现代GHC已将其隐藏在haskell98
和haskell2010
包中。如果您需要编译整个XsdMetz项目,那么可能你应该使用其中一个。但除此之外,更简单的解决方法是
import System.IO.Error (tryIOError)
并在代码中替换tryIOError
而不是try
。
或者,您可以使用Control.Exception.try
,但是您需要在某处放置类型注释以限制其高度重载的类型,以便它知道要捕获的异常类型。