haskel where子句不在范围错误

时间:2014-07-16 02:46:41

标签: haskell haskell-platform

美好的一天,

我是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吗?

3 个答案:

答案 0 :(得分:3)

布局失败。

您的where子句应该比函数名称缩进。 (where子句中的所有绑定必须具有相同的对齐方式;您这样做了。)

do中的所有语句应该具有相同的对齐方式,并且它们应该缩进多于where。 (“结果”和“案例”应该从同一列开始。)

案例中的所有模式应该具有相同的对齐方式,并且它们应该比do语句缩进更多。 (“((右”和“_”应从同一列开始)

Full layout rules

如果你不喜欢空白区域的敏感度,你可以通过提供明确的大括号和分号来(有效地)选择退出布局规则。

答案 1 :(得分:2)

where子句必须在函数名称的一个级别中标记。

答案 2 :(得分:2)

鉴于您的错误消息Not in scope: `try'我猜测布局讨论是一个误解,而您宁愿忘记导入该功能,而不是Prelude。在文件的顶部放置类似

的内容
import Control.Exception (try)

编辑:事实证明,代码假定try的旧Haskell 98 / Haskell 2010语义。不幸的是,现代GHC已将其隐藏在haskell98haskell2010包中。如果您需要编译整个XsdMetz项目,那么可能你应该使用其中一个。但除此之外,更简单的解决方法是

import System.IO.Error (tryIOError)

并在代码中替换tryIOError而不是try

或者,您可以使用Control.Exception.try,但是您需要在某处放置类型注释以限制其高度重载的类型,以便它知道要捕获的异常类型。