[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