通过常见错误类型类

时间:2016-04-17 15:49:18

标签: haskell

我有一些函数返回Except类型(来自transformers包),具有不同的错误类型,但都实现了类Show。如果出现错误,我只想打印消息。

撰写/绑定它们的最佳方法是什么?

我可以在fun*之前转换每个(=<<)的错误类型,或者编写一个(=<<)包装器,它接受所有可显示类型并将它们转换为String s {{{ 1}}?),但感觉很难看。有没有更好的方法,使用类型系统,自动处理所有这些?

示例代码:

RankNTypes

2 个答案:

答案 0 :(得分:1)

最简单的方法是创建一个新的Exception类型(但这需要-XExistentialQuantification)可以显示的异常。

data Exception = forall e . Show e => Exception e

然后,所有需要更改以使代码编译的都是类型签名。

funA :: String -> Except Exception String
funB :: String -> Except Exception T.Text

此外,每当您创建一个异常(上面的代码中没有示例)时,您现在需要将其包装在Exception构造函数中。

throwsA :: String -> Except Exception String
throwsA = throwE . Exception

throwsB :: T.Text -> Except Exception T.Text
throwsB = throwE . Exception

编辑我建议您为异常制作新类型(使用适当的Show),然后从Control.Exception派生Exception。这是更多的开销,但如果您需要在异构异常类型之间来回切换,它可能会让您受益。这就是我的方式。

{-# LANGUAGE DeriveDataTypeable #-}
module Main where

import Data.Typeable
import Control.Exception
import Control.Monad.Trans.Except
import qualified Data.Text as T
import Control.Monad

newtype StrError = StrError String deriving (Show,Typeable)
newtype TxtError = TxtError T.Text deriving (Show,Typeable)

instance Exception StrError
instance Exception TxtError

toErr :: Exception e => Except e a -> Except SomeException a
toErr = mapExcept (either (Left . toException) Right)


funA :: String -> Except StrError String
funA = return

funB :: String -> Except TxtError T.Text
funB = return . T.pack

throwsA :: String -> Except StrError String
throwsA = throwE . StrError

throwsB :: T.Text -> Except TxtError T.Text
throwsB = throwE . TxtError


fun :: String -> IO ()
fun s = case runExcept $ (toErr . funA >=> toErr . funB) s of
            Left e  -> putStrLn $ displayException e
            Right _ -> return ()

main :: IO ()
main = fun "foo"

答案 1 :(得分:0)

withExceptT T.unpack . funB =<< funA s。你的节目是多余的。

使用Control.Lens

fun = void . _Left putStrLn . runExcept . (withExceptT T.unpack . funB <=< funA)