如何将应用验证转换为 return MonadThrow?
How to turn applicative validation to return MonadThrow?
在我看来,在 Haskell 中验证输入数据的惯用方法是通过应用链:
mkMyData :: a -> b -> c -> Maybe MyData
mkMyData x y z =
MyData
<$> validateA x
<*> validateB y
<*> validateC z
其中验证函数本身 return Maybe
值。为了使我的智能构造函数 mkMyData
更灵活,我希望它 return MonadThrow
。也就是说,
mkMyData :: MonadThrow m => a -> b -> c -> m MyData
这是否需要每个验证函数 return MonadThrow
而不是 Maybe
?或者是否有某种方法可以将每个验证的特定 Maybe
结果转换为更通用的 MonadThrow
而不会破坏应用结构并使代码大大复杂化?
或者换个说法?是否值得在基本库函数中争取更通用的 MonadThrow
return 类型,而牺牲更复杂、不那么惯用的代码?
这个问题的答案与相同。您为新验证函数建议的类型,
mkMyData :: MonadThrow m => a -> b -> c -> m MyData
意味着它可以在任何 monad 中工作,只要该 monad 有办法扔东西。如果该函数的实现依赖于能够 return Nothing
或 Just
显式结果,那么它将不满足该条件。
相反,您必须重写当前 return Maybe 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
为参数的函数都已组成,需要以某种方式与您的域相关)。
在我看来,在 Haskell 中验证输入数据的惯用方法是通过应用链:
mkMyData :: a -> b -> c -> Maybe MyData
mkMyData x y z =
MyData
<$> validateA x
<*> validateB y
<*> validateC z
其中验证函数本身 return Maybe
值。为了使我的智能构造函数 mkMyData
更灵活,我希望它 return MonadThrow
。也就是说,
mkMyData :: MonadThrow m => a -> b -> c -> m MyData
这是否需要每个验证函数 return MonadThrow
而不是 Maybe
?或者是否有某种方法可以将每个验证的特定 Maybe
结果转换为更通用的 MonadThrow
而不会破坏应用结构并使代码大大复杂化?
或者换个说法?是否值得在基本库函数中争取更通用的 MonadThrow
return 类型,而牺牲更复杂、不那么惯用的代码?
这个问题的答案与
mkMyData :: MonadThrow m => a -> b -> c -> m MyData
意味着它可以在任何 monad 中工作,只要该 monad 有办法扔东西。如果该函数的实现依赖于能够 return Nothing
或 Just
显式结果,那么它将不满足该条件。
相反,您必须重写当前 return Maybe 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
为参数的函数都已组成,需要以某种方式与您的域相关)。