Skip to content
This repository was archived by the owner on Aug 4, 2023. It is now read-only.

Add functions to convert to / from a Promise to a LazyPromise #12

Merged
merged 3 commits into from
Jun 23, 2021

Conversation

thomashoneyman
Copy link
Contributor

Description of the change

It can be useful to convert a Promise into a LazyPromise or vice versa -- for example, several other libraries like web-fetch can create Promise values, but to be inserted in a chain of binds with LazyPromise values you'll need to convert it first. This PR adds two helper functions for this purpose.


Checklist:

  • Added the change to the changelog's "Unreleased" section with a reference to this PR (e.g. "- Made a change (#0000)")
  • Linked any existing issues or proposals that this pull request should close
  • Updated or added relevant documentation
  • Added a test for the contribution (if applicable)

@thomashoneyman
Copy link
Contributor Author

cc: @robertdp as you helped with this module -- let me know if you have any thoughts!

Comment on lines 75 to 76
toPromise :: forall a. LazyPromise a -> Effect (P.Promise a)
toPromise (LazyPromise p) = unbox =<< p
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two functions could also be renamed toLazyPromise :: Effect (Promise a) -> LazyPromise a and fromLazyPromise :: LazyPromise a -> Effect (Promise a) if desired. I'm open to other names.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current names are good since they're in the Lazy module already - I assume the common usage would be something like: LazyPromise.toPromise, whereas I'd call them Promise.toLazyPromise etc. if they lived in the non-lazy module 🙂

toPromise (LazyPromise p) = unbox =<< p
where
unbox :: forall b. P.Promise (Box b) -> Effect (P.Promise b)
unbox = runEffectFn2 P.then_ (mkEffectFn1 \(Box b) -> pure (P.resolve b))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An unintuitive issue here is promise flattening. LazyPromise uses Box to add structure and prevent flattening. So removing it will reintroduce flattening.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does inferring the type for toPromise add the Flatten constraint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't infer the constraint. Are you envisioning something like this implementation?

toPromise :: forall a. Flatten a b => LazyPromise a -> Effect (P.Promise b)
toPromise (LazyPromise p) = runEffectFn2 P.then_ (mkEffectFn1 \(Box b) -> pure (P.resolve b)) =<< p

or

toPromise :: forall a. Flatten a a => LazyPromise a -> Effect (P.Promise a)

I'm unfortunately not familiar with promise flattening 😬.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I assumed the module P referred to Web.Promise. This is where the type-safe functions that model flattening are.

I would recommend using Web.Promise.then_ and Web.Promise.resolve for these new functions, instead of the internal unsafe functions.

Copy link
Contributor Author

@thomashoneyman thomashoneyman Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this inferred type signature look correct to you?

toPromise :: forall a b c. Flatten a c => Flatten c b => LazyPromise a -> Effect (P.Promise b)
toPromise (LazyPromise p) = Promise.then_ (\(Box b) -> pure (Promise.resolve b)) =<< p

Copy link
Collaborator

@robertdp robertdp Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The double flatten constraint looks redundant to me. It looks like the unnecessary one is coming from the Promise.then_ constraint. How about:

toPromise :: forall a b. Flatten a b => LazyPromise a -> Effect (P.Promise b)
toPromise (LazyPromise p) = runEffectFn2 P.then_ (mkEffectFn1 \(Box b) -> pure (Promise.resolve b)) =<< p

Copy link
Collaborator

@robertdp robertdp Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is now basically identical to your version here: https://github.com/purescript-web/purescript-web-promise/pull/12/files#r655780671

I reckon go with your implementation in the link, you had it right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind taking another look at the latest?

Copy link
Collaborator

@robertdp robertdp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@thomashoneyman thomashoneyman merged commit e0e9dee into master Jun 23, 2021
@thomashoneyman thomashoneyman deleted the to-from-lazy-promise branch June 23, 2021 15:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants