在下面的代码中,还有没有更多惯用的方式来编写checks
函数?
该模式感觉很像(<|>)
应该在这里工作,但是使用
checks s = check1 s <|> check2 s <|> throwError "..."
需要我定义
instance Error ByteString
。{-# LANGUAGE OverloadedStrings #-}
module Bar where
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as BS
import Control.Monad
import Control.Applicative
import Control.Monad.Error
import Data.Monoid
check1 str =
if str == "abc"
then return 1
else throwError ("not equal to abc" :: ByteString)
check2 str =
if str == "def"
then return 2
else throwError ("not equal to def" :: ByteString)
checks str = (check1 str)
`catchError` (const (check2 str))
`catchError` (const (throwError "not abc or def"))
main :: IO ()
main = do
input <- BS.getLine
case checks input of
Left e -> BS.putStrLn $ "Error: " <> e
Right a -> BS.putStrLn "OK"
最佳答案
Alternative
的Either
实例使用Error
约束来生成empty :: Alternative f => f a
的值。在这种情况下,它会执行类似于empty = Left noMsg :: Error e => Either e a
的操作。由于实际上使用<|>
并不需要错误实例,因此,如果您想要不带<|>
的empty
,则可以从半群中使用 Data.Functor.Alt.Alt
。
但是,ExceptT
或Control.Monad.Except
中的Control.Monad.Trans.Except
使用更明智的Monoid
约束,而Bytestring
已经是Monoid
。我认为现在不建议使用ErrorT
。您可能还想使用Bytestring
的列表作为错误类型,否则Bytestring
会被串联在一起且没有空格。
{-# LANGUAGE OverloadedStrings #-}
module Bar where
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as BS
import Control.Monad
import Control.Applicative
import Control.Monad.Trans.Except
import Data.Monoid
check1 str =
if str == "abc"
then return 1
else throwE ["not equal to abc" ]
check2 str =
if str == "def"
then return 2
else throwE ["not equal to def" ]
checks str = check1 str <|> check2 str <|> throwE ["not abc or def"]
main :: IO ()
main = do
input <- BS.getLine
case runExcept $ checks input of
Left e -> mapM_ (BS.putStrLn . ("Error: " <>)) e
Right a -> print a
关于haskell - 用 `catchError`写一串 `(<|>)` -s吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31108139/