sanctuary-js / sanctuary-def

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

Option to assume that all functions are curried #216

Closed danielo515 closed 6 years ago

danielo515 commented 6 years ago

Hello,

I can understand that this library may be used by people that are not committed to all unary functions mantra, but I'm pretty sure that many of it's users are.

For that reason, I don't understand that for getting a very simple signature like this (a -> b -> c) -> (a -> b) -> a -> c I have to writhe this unreadable piece of code:

S = def("sanfu/starling")({})([$.Function([$.Any, $.Function([$.Any, $.Any])]), $.Function([$.Any, $.Any]), $.Any, $.Any])(starling);

This is of course because def does not assume that functions are curried. If that were the case it would be enough to write

[$.Function ([$.Any, $Any, $.Any]), $.Function ([$.Any, $.Any]), $.Any, $.Any]

Which is much more readable and IMO describes better your actual intention. Another shorthand (not related with this) may be to assume that if you don't define the type of a return value (because you should always return something) then it is the type of the last argument. With that extra shortcut you can write the above as:

[$.Function ([$.Any, $Any]), $.Function ([$.Any]), $.Any ]

Which is quite clear I think: A binary function, an Unary function and then any argument

By the way, and this is a small offtopic, the signature I get from this is

(Any -> Any -> Any) -> (Any -> Any) -> Any -> Any

How can I turn it into: (a -> b -> c) -> (a -> b) -> a -> c ?

Regards

davidchambers commented 6 years ago

First, I would define a helper function for defining curried functions:

//    Fn :: Type -> Type -> Type
const Fn = x => y => $.Function ([x, y]);

Next, I would define some type variables:

const a = $.TypeVariable ('a');
const b = $.TypeVariable ('b');
const c = $.TypeVariable ('c');

Finally, I would define the starling combinator:

//    starling :: (a -> b -> c) -> (a -> b) -> a -> c
const starling =
def ('starling')
    ({})
    ([Fn (a) (Fn (b) (c)), Fn (a) (b), a, c])
    (f => g => x => f (x) (g (x)));

The Sanctuary source code provides several examples of idiomatic use of sanctuary-def. :)

danielo515 commented 6 years ago

Hey ! Thank you very much! That seems good enough. I didn't know about TypeVariable class