Skip to content

liftMaybe, liftEither, liftExceptT #196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jamesdbrock opened this issue May 12, 2022 · 4 comments · Fixed by #212
Closed

liftMaybe, liftEither, liftExceptT #196

jamesdbrock opened this issue May 12, 2022 · 4 comments · Fixed by #212

Comments

@jamesdbrock
Copy link
Member

“Validation Parsers”

liftMaybe :: forall s m a. Monad m => (Unit -> String) -> Maybe a -> ParserT s m a
liftEither :: forall s m a. Monad m => Either String a -> ParserT s m a
liftExceptT :: forall s m a. Monad m => ExceptT String m a -> ParserT s m a

Similar to
https://pursuit.purescript.org/packages/purescript-transformers/6.0.0/docs/Control.Monad.Error.Class#v:liftMaybe

Similar to
https://pursuit.purescript.org/packages/purescript-protobuf/2.1.2/docs/Protobuf.Library#v:parseMaybe

See also #84

See also https://pursuit.purescript.org/packages/purescript-lazy/6.0.0/docs/Data.Lazy

Or perhaps these should be called maybeParserT, eitherParserT, exceptParserT?

@natefaubion
Copy link
Contributor

Can these all be written in terms of MonadError? Why should they be specialized to ParserT?

@jamesdbrock
Copy link
Member Author

Can these all be written in terms of MonadError?

Yes, in like one line.

Why should they be specialized to ParserT?

Mostly as documentation to encourage users to “parse, don’t validate?”

@natefaubion
Copy link
Contributor

To clarify, if they are implemented only with MonadError, then their utility is far greater than just ParserT, and it would be worth potentially upstreaming them to transformers if they don't exist.

@jamesdbrock
Copy link
Member Author

jamesdbrock commented May 29, 2022

Why should they be specialized to ParserT?

In Control.Monad.Error.Class we have

-- | Lift a `Maybe` value to a MonadThrow monad.
liftMaybe :: forall m e a. MonadThrow e m => e -> Maybe a -> m a

-- | Lift an `Either` value to a MonadThrow monad.
liftEither :: forall m e a. MonadThrow e m => Either e a -> m a

It's awkward for parsing users to use these functions because the type for e would be ParseError, which has constructor ParseError String Position. We don't want to require users to supply the Position argument of the constructor. We would rather specialize the e type to String and use the current parsing position.

Also it can be expensive to construct Strings, especially on a parsing hot path where we expect a parsing failure to be rare, so in liftMaybe it makes sense to defer the String construction.

So with those adjustments we get

liftMaybe :: forall s m a. Monad m => (Unit -> String) -> Maybe a -> ParserT s m a
liftEither :: forall s m a. Monad m => Either String a -> ParserT s m a

As for liftExceptT (and liftMaybeT?) it”s the same as the above, with the stipulation that if the user needs some special base monad feature for parsing then maybe they also need the special base monad feature for validation. This could be true while parsing DataViews with a base monad Effect, for example.

So that would be

liftMaybeT :: forall s m a. Monad m => (Unit -> String) -> MaybeT m a -> ParserT s m a
liftExceptT :: forall s m a. Monad m => ExceptT String m a -> ParserT s m a

Those two functions don't seem to exist in transformers already but if they did then they would look like

-- | Lift a `MaybeT` value to a MonadThrow monad.
liftMaybeT :: forall m e a. MonadThrow e m => e -> MaybeT m a -> m a

-- | Lift an `ExceptT` value to a MonadThrow monad.
liftExceptT :: forall m e a. MonadThrow e m => ExceptT e m a -> m a

jamesdbrock added a commit that referenced this issue Nov 9, 2022
jamesdbrock added a commit that referenced this issue Nov 9, 2022
@jamesdbrock jamesdbrock linked a pull request Nov 9, 2022 that will close this issue
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants