当前位置:  开发笔记 > 程序员 > 正文

Haskell Safe IO

如何解决《HaskellSafeIO》经验,为你挑选了1个好方法。

我正在尝试编写一个简单的函数来安全地读取文件(如果存在),如果文件不存在则不执行任何操作:

safeRead :: String -> IO ()
safeRead path = readFile path `catch` handleExists
  where handleExists e
          | isDoesNotExistError e = return ()
          | otherwise = throwIO e

这在编译时失败了

Couldn't match type ‘[Char]’ with ‘()’
Expected type: IO ()
  Actual type: IO String
In the first argument of ‘catch’, namely ‘readFile path’
In the expression: readFile path `catch` handleExists

这是有道理:t readFilereadFile :: FilePath -> IO String.例如返回IO String(并且IO String不相同IO ())的函数

将签名更改为 String -> IO String

Couldn't match type ‘()’ with ‘[Char]’
Expected type: IOError -> IO String
  Actual type: IOError -> IO ()
In the second argument of ‘catch’, namely ‘handleExists’
In the expression: readFile path `catch` handleExists

这也是有道理的,因为handleExists有类型 IO ()

为了保存每个人的查找,catch被导入: import Control.Exception catch的签名是: catch :: Exception e => IO a -> (e -> IO a) -> IO a

我真正的问题是,如何在Haskell中编写这种错误安全,灵活的代码?更具体地说,我必须对此功能做出哪些改变才能让它同时处理成功案例和失败案例?



1> Sebastian Re..:

你需要找出你希望你的功能实际做什么.

如果它成功读取文件,您希望它以字符串形式返回内容.

如果它失败了,你真的想要它做什么?返回一个空字符串或其他一些后备内容?然后你可以在第一种情况下改变return ()to .return ""handleExists

但是如果你想在返回类型中指出错误,那么你需要返回一个不同的类型String.正如卡斯滕所说,你可以回归Maybe StringJust theString为成功和Nothing错误付出代价.或者,Either如果您想要一些错误消息,则可以返回.

我觉得对于这个特定的功能,Maybe String最有意义,因为你只捕获不存在的文件并重新抛出其他错误.然后你的代码需要看起来像这样:

safeRead :: String -> IO (Maybe String)
safeRead path = (fmap Just $ readFile path) `catch` handleExists
  where
    handleExists :: IOException -> IO (Maybe String)
    handleExists e
      | isDoesNotExistError e = return Nothing
      | otherwise = throwIO e

这里我们将结果包装readFile在a中Just以满足类型要求,并在错误情况下返回Nothing而不是单位.

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有