Haskell 我无法通过尝试获得 ReadFile 异常
Haskell I can not get exception ReadFile with try
我有一个函数 "management" 检查参数和 return 一个 Maybe (String):
- 如果没有参数 -> return 没有
- 如果我的参数等于“-h” -> Return 字符串帮助
当我获取一个文件并检查该文件是否存在时,我的问题就来了。
Couldn't match expected type ‘Maybe String’
with actual type ‘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)
有几个问题
函数应用($
)的优先级低于绑定(>>=
)
你说:
try $ readFile file >>= \res...
这意味着
try ( readFile file >>= \res... )
但你想要:
try ( readFile file ) >>= \res...
IO (Maybe a)
和 Maybe a
是不同的
您有一个使用 IO 的函数(通过 readFile
和 try
),但许多情况下 return 没有 IO 结果(Nothing
和 Just content
).
解决方案:Return 通过 return Nothing
或 pure Nothing
将值提升到 IO monad。
异常类型不明确
try
函数可以捕获任何异常类型,看签名就知道了:
try :: Exception e => IO a -> IO (Either e a)
当你完全忽略异常时,你让类型检查器没有任何信息来决定 e
应该是什么。在这些情况下,显式类型签名很有用,例如:
Left (e::SomeException) -> pure Nothing
managagment
部分
managagment ["a","b"]
未定义,任何长度超过一的输入列表也是如此。考虑以下的最终方程式定义:
managagment _ = managagment ["-h"]
或更直接:
managagment _ = pure $ Just help
样式和其他注释
managagment
应该是 management
Just (foo)
一般是Just foo
help
不是 return 字符串的函数。它是一个字符串类型的值。
- 示例不完整,缺少导入和
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
我有一个函数 "management" 检查参数和 return 一个 Maybe (String):
- 如果没有参数 -> return 没有
- 如果我的参数等于“-h” -> Return 字符串帮助
当我获取一个文件并检查该文件是否存在时,我的问题就来了。
Couldn't match expected type ‘Maybe String’ with actual type ‘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)
有几个问题
函数应用($
)的优先级低于绑定(>>=
)
你说:
try $ readFile file >>= \res...
这意味着
try ( readFile file >>= \res... )
但你想要:
try ( readFile file ) >>= \res...
IO (Maybe a)
和 Maybe a
是不同的
您有一个使用 IO 的函数(通过 readFile
和 try
),但许多情况下 return 没有 IO 结果(Nothing
和 Just content
).
解决方案:Return 通过 return Nothing
或 pure Nothing
将值提升到 IO monad。
异常类型不明确
try
函数可以捕获任何异常类型,看签名就知道了:
try :: Exception e => IO a -> IO (Either e a)
当你完全忽略异常时,你让类型检查器没有任何信息来决定 e
应该是什么。在这些情况下,显式类型签名很有用,例如:
Left (e::SomeException) -> pure Nothing
managagment
部分
managagment ["a","b"]
未定义,任何长度超过一的输入列表也是如此。考虑以下的最终方程式定义:
managagment _ = managagment ["-h"]
或更直接:
managagment _ = pure $ Just help
样式和其他注释
managagment
应该是management
Just (foo)
一般是Just foo
help
不是 return 字符串的函数。它是一个字符串类型的值。- 示例不完整,缺少导入和
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