haskell - 用 `catchError`写一串 `(<|>)` -s吗?

标签 haskell error-handling monad-transformers

在下面的代码中,还有没有更多惯用的方式来编写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"

最佳答案

AlternativeEither实例使用Error约束来生成empty :: Alternative f => f a的值。在这种情况下,它会执行类似于empty = Left noMsg :: Error e => Either e a的操作。由于实际上使用<|>并不需要错误实例,因此,如果您想要不带<|>empty,则可以从半群中使用 Data.Functor.Alt.Alt

但是,ExceptTControl.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/

相关文章:

Swift 显示来自枚举参数的错误消息

PHP curl 超时错误检测

Haskell 作为一种脚本语言

haskell - new-template.cabal 和 stack.yaml 的区别

java - 懒惰斐波那契数列

haskell - 如何使免费的 monad 解释器递归?

scala - IO 和 Future[Option] monad 转换器

haskell - 将元组转换为可折叠

ios 检查空对象

haskell - 生成状态列表的最佳方法(Haskell)