如何将此函数从 ExceptT 转换为 Haskell 中的 Except?
How can I convert this function from ExceptT to Except in Haskell?
我对 Except
感到很困惑,特别是因为网络上没有好的教程。我不知道如何将此函数从 ExceptT
转换为 Except
:
data Error = Empty deriving (Show)
badFunction :: ExceptT Error IO ()
badFunction = throwError Empty
main :: IO ()
main = do
caught_result <- runExceptT badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
badFunction
应该是 ExceptT Error IO ()
的原因是因为 runExceptT
的类型是 runExceptT :: ExceptT e m a -> m (Either e a)
。由于您的 main 类型为 main :: IO ()
,这意味着 runExceptT badFunction
需要是 IO …
,因此 ExceptT e m a
中的 m
应该是 IO
。
但是你本身并不需要这个,你的 badFunction
不做任何 IO
,所以你可以将它定义为 Except
:
badFunction :: <b>Except</b> Error ()
badFunction = throwE Empty
然后你可以在一个IO ()
中使用它,通过使用runIdentity
来获取标识出来的值,然后使用pure
来“wrap" IO
:
中的结果
main :: IO ()
main = do
caught_result <- pure (<b>runIdentity</b> (runExceptT badFunction))
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
但是我们可以在 main
中使用 let …
子句并删除 pure
:
main :: IO ()
main = do
let caught_result = <b>runIdentity</b> (runExceptT badFunction)
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
为, the combination of runIdentity
and runExceptT
is runExcept :: Except e a -> Either e a
,所以我们可以改写为:
main :: IO ()
main = do
let caught_result = <b>runExcept</b> badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
你写
badFunction :: ExceptT Error IO ()
badFunction = throwError Empty
这表明确实如此 IO
。但它没有做任何 IO
。正如 Willem Van Onsem 指出的那样,一种选择是通过使用 Except
来表示:
badFunction :: Except Error ()
根据 Except
的定义,这等同于
badFunction :: ExceptT Error Identity ()
还有第三种选择:
badFunction :: Monad m => ExceptT Error m ()
这给了你充分的灵活性!
runExcept badFunction :: Either Error ()
runExceptT badFunction :: Monad m => m (Either Error ())
所以如果你选择,你可以写
main :: IO ()
main = do
caught_result <- runExceptT badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
你想的更清楚。
我对 Except
感到很困惑,特别是因为网络上没有好的教程。我不知道如何将此函数从 ExceptT
转换为 Except
:
data Error = Empty deriving (Show)
badFunction :: ExceptT Error IO ()
badFunction = throwError Empty
main :: IO ()
main = do
caught_result <- runExceptT badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
badFunction
应该是 ExceptT Error IO ()
的原因是因为 runExceptT
的类型是 runExceptT :: ExceptT e m a -> m (Either e a)
。由于您的 main 类型为 main :: IO ()
,这意味着 runExceptT badFunction
需要是 IO …
,因此 ExceptT e m a
中的 m
应该是 IO
。
但是你本身并不需要这个,你的 badFunction
不做任何 IO
,所以你可以将它定义为 Except
:
badFunction :: <b>Except</b> Error ()
badFunction = throwE Empty
然后你可以在一个IO ()
中使用它,通过使用runIdentity
来获取标识出来的值,然后使用pure
来“wrap" IO
:
main :: IO ()
main = do
caught_result <- pure (<b>runIdentity</b> (runExceptT badFunction))
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
但是我们可以在 main
中使用 let …
子句并删除 pure
:
main :: IO ()
main = do
let caught_result = <b>runIdentity</b> (runExceptT badFunction)
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
为runIdentity
and runExceptT
is runExcept :: Except e a -> Either e a
,所以我们可以改写为:
main :: IO ()
main = do
let caught_result = <b>runExcept</b> badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
你写
badFunction :: ExceptT Error IO ()
badFunction = throwError Empty
这表明确实如此 IO
。但它没有做任何 IO
。正如 Willem Van Onsem 指出的那样,一种选择是通过使用 Except
来表示:
badFunction :: Except Error ()
根据 Except
的定义,这等同于
badFunction :: ExceptT Error Identity ()
还有第三种选择:
badFunction :: Monad m => ExceptT Error m ()
这给了你充分的灵活性!
runExcept badFunction :: Either Error ()
runExceptT badFunction :: Monad m => m (Either Error ())
所以如果你选择,你可以写
main :: IO ()
main = do
caught_result <- runExceptT badFunction
case caught_result of
Left _ -> putStrLn "caught some error"
Right _ -> putStrLn "no errors were caught"
你想的更清楚。