[Haskell-cafe] Lift data from IO to Validation
Debasish Ghosh
ghosh.debasish at gmail.com
Sat Jan 4 19:26:42 UTC 2020
Thanks for all the suggestions .. Here's an example of a validation
function with Reader Env ..
validateOpenDate :: ZonedTime -> Reader Env (Validation [String] ZonedTime)
validateOpenDate openDate = do
now <- asks curTime
if zonedTimeToUTC openDate > zonedTimeToUTC now
then return $ Failure ["Account open date cannot be in the future"]
else return $ Success openDate
I have a few such functions and I wire them together to form a smart
constructor that builds an ADT ..
makeAccount :: String -> String -> ZonedTime -> IO (Validation [String]
Account)
makeAccount no name openDate = do
env <- Env <$> getZonedTime
flip runReader env $ do
validAccountNo <- validateAccountNo no
validAccountName <- validateAccountName name
validOpeningDate <- validateOpenDate openDate
return $ return $ Account <$> validAccountNo <*> validAccountName <*>
validOpeningDate
Does this look like an idiomatic implementation ? Is there any scope to
make things better ? I compose applicatively as I need to accumulate all
validation errors. And also Validation does not have a Monad ..
regards.
On Sat, Jan 4, 2020 at 9:20 PM Viktor Dukhovni <ietf-dane at dukhovni.org>
wrote:
> On Sat, Jan 04, 2020 at 08:28:50PM +0530, Debasish Ghosh wrote:
>
> > I am trying to validate a bunch of inputs and found the package
> > Data.Validation. I am also using Data.Time for date and time. I have a
> > function like this.
> >
> > validateOpenDate :: ZonedTime -> Validation [String] ZonedTime
> >
> > It's supposed to validate a date for which I need to fetch the current
> > date and time. I can do that with getZonedTime :: IO ZonedTime. I want
> > to check if the current time is less than the date time I pass to the
> > function and return an appropriate Validation.
>
> This function is not pure. It needs an external input that affects its
> output. Therefore, the honest type of this function is either:
>
> -- | Validate date relative to current time
> validateOpenDate :: ZonedTime -> IO (Validation [String] ZonedTime)
>
> or (with the caller doing the time lookup):
>
> -- | Validate date relative to supplied time
> validateOpenDate :: ZonedTime -> ZonedTime -> Validation [String]
> ZonedTime
>
> The "supplied time could be generalized to an "Environment" that carries
> whatever context information might be needed:
>
> type Env = Env { curTime :: !ZonedTime }
>
> With all the validation functions now:
>
> validateOpenDate :: ZonedTime -> Reader Env (Validation [String]
> ZonedTime)
> validateOpenData inputDate = do
> now <- asks curTime
> if inputDate > now
> then ...
> else ...
>
> and then
>
> import Control.Monad.Reader
>
> main :: IO ()
> main = do
> env <- Env <$> getZonedTime
> flip runReader env $ do
> -- computations doing validation relative to the environment
>
> > The question is how do I lift the result from IO into the Validation?
>
> The only way to do that without changing the output type is to lie, and
> use "unsafePerformIO" to extract the date inside a pure function. This
> is not recommended.
>
> > Or is there any alternative strategy that I should consider for this
> > validation ? I have a number of other validations which follow the
> > same strategy but don't have the IO. My final goal is to be able to
> > compose all these validations applicatively to prepare a final ADT in
> > a smart constructor.
>
> You should be able "compose" the validations in the context of an
> environment. Either Monadically, or Applicatively.
>
> --
> Viktor.
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
--
Debasish Ghosh
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20200105/11e231ca/attachment.html>
More information about the Haskell-Cafe
mailing list