sanctuary-js / sanctuary-def

Run-time type system for JavaScript
MIT License
294 stars 23 forks source link

Usage of curry with promises #215

Closed wdalmut closed 6 years ago

wdalmut commented 6 years ago

Hi guys,

i am in a condition that i cannot figure out.

I want to curry a function that will return a promise. Let suppose there is something like:

const getUser = (token, id) => Promise.resolve({id: 1});

Now i think that can get a curried version of this function

const S = require('sanctuary');
const getUserAuthenticated = S.curry2(getUser)("Bearer test")

So now i get use the getUserAuthenticated function and i can map it when i need to, but sadly i get a type error because the promise is not a correct type.

getUserAuthenticated(1).then(...)
TypeError: Unrecognized value

curry2 :: ((a, b) -> c) -> a -> b -> c
                     ^
                     1

1)  [object Promise] :: (no types)

The value at position 1 is not a member of any type in the environment.

The environment contains the following types:                                                                                            

  - Function                                                                                                                             
  - Arguments                                                                                                                            
  - Array d
...

Why there is a limitation with curry and types?

Thanks Walter

gabejohnson commented 6 years ago

I think this may be an issue w/ there being no Promise type defined in sanctuary-def.

This issue could be resolved by adding your own type definition @wdalmut. Though a built-in type such as Promise should probably have a definition (even though it's use may be discouraged).

You could also try using https://github.com/fluture-js/Fluture instead of promises.

@davidchambers please correct me if I've gotten anything wrong.

davidchambers commented 6 years ago

Here's a working example to get you unstuck, @wdalmut:

'use strict';

const {create, env} = require ('sanctuary');
const $ = require ('sanctuary-def');

//    PromiseType :: Type -> Type -> Type
const PromiseType = $.BinaryType
  ('my-package/Promise')
  ('https://example.com/my-package#Promise')
  (x => Object.prototype.toString.call (x) === '[object Promise]')
  (p => [])
  (p => []);

const S = create ({
  checkTypes: true,
  env: env.concat ([PromiseType ($.Unknown) ($.Unknown)]),
});

console.log (S.I (Promise.resolve (42)));

@davidchambers please correct me if I've gotten anything wrong.

Your answer was spot on, Gabe! I think providing a Promise type constructor is a good idea.

wdalmut commented 6 years ago

thanks guys :+1:

davidchambers commented 6 years ago

No problem, Walter. Let us know if you encounter other issues.

efrister commented 6 years ago

Hi guys,

what's the preferred way to do async operations when working with Sanctuary: using Promises and defining a custom type as above, or using Fluture? Or something entirely different?

davidchambers commented 6 years ago

I unreservedly recommend Fluture. :butterfly: