问题描述
我尝试使用 Applicatives
和 Either Monad
验证 Record
的构造.它工作正常.但是我看不到所有错误消息.只有第一个可见,因为任一Monad
的 Right
路径都会忽略它们.
I tried to validate the construction of a Record
with Applicatives
and the Either Monad
. It works fine. But I can't see all Error Messages. Only the first is visible because the Right
Path of the Either Monad
ignores them.
这是我的代码:
import Data.Either (either)
import Text.Printf (printf)
data Record = Record
{ fieldA :: String
, fieldB :: String
, fieldC :: String
} deriving (Show, Eq)
type Err = String
setField :: String -> String -> Either Err String
setField field value
| length value > 0 = Right value
| otherwise = Left $ printf "value for field %s is to short" field
setFieldA :: String -> Either Err String
setFieldA = setField "fieldA"
setFieldB :: String -> Either Err String
setFieldB = setField "fieldB"
setFieldC :: String -> Either Err String
setFieldC = setField "fieldC"
makeRecord :: Either Err Record
makeRecord = Record
<$> setField "fieldA" "valueA"
<*> setField "fieldB" "valueB"
<*> setField "fieldC" "valueC"
makeRecord' :: Either Err Record
makeRecord' = Record
<$> setFieldA "valueA"
<*> setFieldB "valueB"
<*> setFieldC "valueC"
recordFromEither :: Either Err Record -> Maybe Record
recordFromEither r =
case r of
Right v -> Just $ v
Left _ -> Nothing
main :: IO ()
main = putStrLn $ output
where
output = case makeRecord of
Right v -> show v
Left err -> show err
main' :: IO ()
main' = putStrLn $ either id show makeRecord'
我的问题是如何保留和显示所有错误消息.也许和州立莫纳德一起?
My question is how can I keep and display all error messages. Maybe with the State Monad?
推荐答案
这是因为 Ething
Applicative
实例的工作方式.您可以做的是将 Ething
换成 newtype
:
That's because of the way the Either
Applicative
instance works. What you can do is to wrap Either
in a newtype
:
newtype Validation e r = Validation (Either e r) deriving (Eq, Show, Functor)
然后给它另一个 Applicative
实例:
instance Monoid m => Applicative (Validation m) where
pure = Validation . pure
Validation (Left x) <*> Validation (Left y) = Validation (Left (mappend x y))
Validation f <*> Validation r = Validation (f <*> r)
您现在可以使用< $>
和< *>
组成 Validation [Err] Record
结果.有关更多详细信息,请参阅我在应用验证上的文章.
You can now use <$>
and <*>
to compose a Validation [Err] Record
result. See my article on Applicative validation for more details.
这篇关于如何收集Either Monad中的所有错误消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!