【问题标题】:Haskell I can not get exception ReadFile with tryHaskell我无法通过尝试获得异常ReadFile
【发布时间】:2019-11-22 00:37:40
【问题描述】:

我有一个“管理”函数,它检查参数并返回一个可能(字符串):

  • 如果没有参数->返回Nothing
  • 如果我的参数等于“-h” -> 返回字符串帮助

当我得到一个文件并检查这个文件是否存在时,我的问题就出现了。

无法匹配预期的类型“可能是字符串” 具有实际类型‘IO (Either e0 a2)’

managagment :: [String] -> Maybe (String)
managagment [] = Nothing
managagment ["-h"] = Just (help)
managagment [file] = try $ readFile file >>= \result -> case result of
                                                        Left e -> Nothing
                                                        Right content -> Just (content)

【问题讨论】:

  • 你认为readFile的类型是什么?
  • 同理,你认为try的类型是什么?检查时 ghci 会说什么?
  • Ghci return "IO (Either e a)",Either 由 Left 和 Right 两个构造函数组成。我就是这样做的
  • Just "help",而不是Just help
  • help 是一个返回字符串的函数(help :: String)

标签: haskell try-catch maybe either


【解决方案1】:

有几个问题

函数应用程序 ($) 的优先级低于绑定 (>>=)

你说:

try $ readFile file >>= \res...

这意味着

try ( readFile file >>= \res... )

但你想要:

try ( readFile file ) >>= \res...

IO (Maybe a)Maybe a 是不同的

您有一个使用 IO 的函数(通过 readFiletry),但许多情况不返回 IO 结果(NothingJust content)。

解决方案:通过return Nothingpure Nothing 返回以将值提升到 IO monad。

异常类型不明确

try函数可以捕获任何异常类型,看签名即可:

try :: Exception e => IO a -> IO (Either e a)

当您完全忽略异常时,您会离开类型检查器而没有任何信息来决定 e 应该是什么。在这些情况下,显式类型签名很有用,例如:

  Left (e::SomeException) -> pure Nothing

managagment 不完整

managagment ["a","b"] 未定义,任何长度超过 1 的输入列表也是如此。考虑一个最终的等式定义:

managagment _ = managagment ["-h"]

或者更直接:

managagment _ = pure $ Just help

样式和其他注释

  • managagment 应该是 management
  • Just (foo) 一般为Just foo
  • help 不是返回字符串的函数。它是一个字符串类型的值。
  • 示例不完整,缺少导入和help

固定代码

请考虑:

#!/usr/bin/env cabal
{- cabal:
    build-depends: base
-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase          #-}
import Control.Exception (try, SomeException)

main :: IO ()
main = print =<< management []

help :: String
help = "so helpful"

management :: [String] -> IO (Maybe String)
management [] = pure Nothing
management ["-h"] = pure $ Just help
management [file] =
    try (readFile file) >>=
      \case
         Left (e::SomeException) -> pure Nothing
         Right content -> pure $ Just content
management _ = pure $ Just help

然后这样测试:

% chmod +x x.hs
% ./x.hs

【讨论】:

    猜你喜欢
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 2011-12-05
    • 1970-01-01
    相关资源
    最近更新 更多