Validation 如何将应用程序验证转换为返回MonadThrow?

Validation 如何将应用程序验证转换为返回MonadThrow?,validation,haskell,error-handling,monads,applicative,Validation,Haskell,Error Handling,Monads,Applicative,在我看来,验证Haskell中输入数据的惯用方法是通过应用程序链: mkMyData :: a -> b -> c -> Maybe MyData mkMyData x y z = MyData <$> validateA x <*> validateB y <*> validateC z 这是否要求每个验证函数返回MonadThrow,而不是Maybe?或者,是否有某种方法可以将每次

在我看来,验证Haskell中输入数据的惯用方法是通过应用程序链:

mkMyData :: a -> b -> c -> Maybe MyData
mkMyData x y z =
    MyData
        <$> validateA x
        <*> validateB y
        <*> validateC z
这是否要求每个验证函数返回
MonadThrow
,而不是
Maybe
?或者,是否有某种方法可以将每次验证的特定
结果
转换为更通用的
MonadThrow
,而不破坏应用程序结构并使代码复杂化


或者换个说法?是否值得在基本库函数中使用更通用的
MonadThrow
返回类型,而牺牲更复杂、更不惯用的代码?

对此的答案与。您为新验证功能建议的类型

mkMyData :: MonadThrow m => a -> b -> c -> m MyData
这意味着它可以在任何单子中工作,只要该单子有扔东西的方法。如果该函数的实现依赖于能够显式返回
Nothing
Just
结果,那么它将不满足该条件

相反,您必须重写当前返回
的函数(可能是a
),以依赖MonadThrow。例如,代替

validateA :: a -> Maybe t
validateA x | acceptable x = Just $ convert x
            | otherwise = Nothing
你需要写信

validateA :: MonadThrow m => a -> m t
validateA x | acceptable x = pure $ convert x
            | otherwise = throwM $ problemWith x

(所有以
x
为参数的函数都是虚构的,需要以某种方式与您的域相关)。

我的直觉是,这将是过早的推广。一方面,在一般情况下,你不知道你想扔什么。另一方面,如果您碰巧知道在一个具体情况下要抛出什么,您可以使用不同的
MonadThrow
实例(另请参见)重新实现
mkMyData
,或者在适当的地方插入
maybe(throwmmyerr)return
。感谢您的洞察力。我想说的是:首先,MonadThrow风格的错误处理(还没有)普及;其次,没有适配器函数,我需要自己编写。因此,最好不要将其作为默认值。
validateA :: MonadThrow m => a -> m t
validateA x | acceptable x = pure $ convert x
            | otherwise = throwM $ problemWith x