rescript-lang / rescript-compiler

The compiler for ReScript.
https://rescript-lang.org
Other
6.65k stars 442 forks source link

Add bs.curry #3060

Closed Risto-Stevcev closed 5 years ago

Risto-Stevcev commented 5 years ago

This proposal is to add bs.curry, which would treat all arrows in an external declaration as curried functions. Right now external declarations are auto-uncurried, which is the correct default since javascript isn't curried by default. But some javascript libraries have a curried API, and it gets tedious to translate them. This is also useful for APIs that return a function, and would avoid needing to use [@bs] in many cases

Before bs.curry:

external _forEach: ('a -> unit) -> ('a t -> unit [@bs]) = "forEach"
[@@bs.module "callbag-basics"]

let forEach f e = (_forEach f) e [@bs] 

After bs.curry:

external forEach: ('a -> unit) -> 'a t -> unit = ""
[@@bs.curry] [@@bs.module "callbag-basics"]
bobzhang commented 5 years ago

hi @Risto-Stevcev you can already do it like something as below:

type 'a fn = 'a t-> unit
external forEach: ('a -> unit) ->  'a fn= "" [@@bs.module "callbag-basics"]
Risto-Stevcev commented 5 years ago

Ugh... I tried this first and it wasn't working for me, I guess I need to get my eyes checked

Risto-Stevcev commented 4 years ago

Is is possible to reopen this and reconsider?

If I use the fn technique that you described:

type ('a, 'b) fn = 'a -> 'b
external map : ('a -> 'b) -> ('a stream, 'b stream) fn = "map" [@@bs.module "./index"]

Then the type signature gets hard to read because now it's obscured in a type:

('a -> 'b) -> ('a stream, 'b stream) fn

As is the error:

Error: This expression has type
         ('a stream, unit stream) fn = 'a stream -> unit stream
       but an expression was expected of type int -> 'b
       Type 'a stream is not compatible with type int 

But if I use the [@bs] method described originally:

external _map : ('a -> 'b) -> ('a stream -> 'b stream [@bs]) = "map" [@@bs.module "./index"]
let map' f x = (_map f) x [@bs]

let x = 100 |> map' (fun _ -> ())

The type of map' shows nicely with the IDE:

('a -> 'b) -> 'a stream -> 'b stream

and the error is easier to read;

Error: This expression has type 'a stream -> unit stream
       but an expression was expected of type int -> 'b
       Type 'a stream is not compatible with type int 

except now bucklescript is generating two functions instead of one, leading to a bunch of duplicate code.

bobzhang commented 4 years ago

did you try uncurried function, it's really good now (in 7.3)

Risto-Stevcev commented 4 years ago

Ah thanks! I didn't see the new release, that solves it for me