Haskell 如何使用data.validation组合错误
我正在使用精彩的Data.Validation包进行验证。但是,对于复杂类型,我无法正确地组合它们 我分别为电子邮件和密码电子邮件和密码创建了类型。我已经使用Data.Validation包创建了可以累积的验证和错误。我制作了一个新类型,名为data Creds=电子邮件密码。现在,我无法从电子邮件和密码中累积错误 `Haskell 如何使用data.validation组合错误,haskell,haskell-lens,Haskell,Haskell Lens,我正在使用精彩的Data.Validation包进行验证。但是,对于复杂类型,我无法正确地组合它们 我分别为电子邮件和密码电子邮件和密码创建了类型。我已经使用Data.Validation包创建了可以累积的验证和错误。我制作了一个新类型,名为data Creds=电子邮件密码。现在,我无法从电子邮件和密码中累积错误 ` 我将使用EmailError PasswordError作为组合类型。您可以改为创建自定义的总和类型 mkCreds::Text->Text->Validation[EmailE
我将使用
EmailError PasswordError
作为组合类型。您可以改为创建自定义的总和类型
mkCreds::Text->Text->Validation[EmailError PasswordError]Creds
mkCreds e p=Creds first Left(mke)first Right(mkp)
这有三件事:
- 使用
和mkEmail
验证每个部分mkPassword
- 使用
和左一
右一
- 使用
和
``
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveGeneric #-}
module ErrorComposition
()
where
import Data.Text as T
import Data.Validation
import Control.Lens
------------------------------------
-- validations and errors for Email
------------------------------------
data Email = Email
{
email :: Text
} deriving (Show)
data EmailError = EmailNoDotError | EmailNoPeriodError
deriving (Show)
noDot :: Email -> Validation [EmailError] ()
noDot x = if "." `isInfixOf` (email x)
then _Success # ()
else _Failure # [EmailNoDotError]
noPeriod :: Email -> Validation [EmailError] ()
noPeriod x = if "@" `isInfixOf` (email x)
then _Success # ()
else _Failure # [EmailNoPeriodError]
validateEmail :: Email -> Validation [EmailError] ()
validateEmail e = noDot e <* noPeriod e
mkEmail :: Text -> Validation [EmailError] Email
mkEmail e = pure (Email e) <* validateEmail (Email e)
-----------------------------------------------------------
-- validations for password and errors
-- --------------------------------------------------------
data Password = Password
{
password :: Text
} deriving Show
data PasswordError = MinLengthPasswordError | NotStrongPasswordError
deriving (Show)
minLength :: Int -> Password -> Validation [PasswordError] ()
minLength n x | T.length (password x) >= n = _Success # ()
| otherwise = _Failure # [MinLengthPasswordError]
notStrong :: Password -> Validation [PasswordError] ()
notStrong x = if "strong" `isInfixOf` (password x)
then _Success # ()
else _Failure # [NotStrongPasswordError]
validatePassword :: Password -> Validation [PasswordError] ()
validatePassword p = minLength 7 p <* notStrong p
mkPassword :: Text -> Validation [PasswordError] Password
mkPassword p = pure (Password p) <* validatePassword (Password p)
--------------------------------------------------------------------
-- Domain Modelling for an Creds type
-- The expectation is errors from email and password should be combined
-- ----------------------------------------------------------------
data Creds = Creds
{
credsEmail :: Email
, credsPassword:: Password
} deriving (Show)
data CredsError = EmailError | PasswordError
deriving (Show)
validateCreds :: Creds -> Validation [CredsError] ()
--validateCreds (Creds e p) = validateEmail e <* validatePassword p
validateCreds = undefined
mkCreds :: Email -> Password -> Validation [CredsError] Creds
mkCreds e p = pure (Creds e p) <* validateCreds (Creds e p)
ErrorComposition> let e1= mkEmail "bob"
*ErrorComposition> show e1
"Failure [EmailNoDotError,EmailNoPeriodError]"
*ErrorComposition> let p1 = mkPassword "he"
*ErrorComposition> show p1
"Failure [MinLengthPasswordError,NotStrongPasswordError]"
*ErrorComposition> let c1 = mkCreds (Email "bob") (Password "he")
What Am I expecting?
Failure [EmailNoDotError, EmailNoPeriodError, MinLengthPasswordError,NotStrongPasswordError]
1. Is it possible to get the above result?
2. Even if the above result is not possible because the error types differ, atleast, I'm looking for a way to get the following:
Failure ["EmailNoDotError", "EmailNoPeriodError",
"MinLengthPasswordError,"NotStrongPasswordError"]
3. Essentially could you please help me in fixing the validateCreds function above in the code?