sanctuary-js / sanctuary-def

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

$.Function ([a, b]) not behaving as expected #221

Closed hugonteifeh closed 5 years ago

hugonteifeh commented 5 years ago

Hi guys! First thing first i wanna say that I'm so excited about the brilliant work that has been done in sanctuary, especially the sanctuary-def module. Following the documentation i was defining functions and everything worked fine, but then i tried to implement the map method after checking the example in the documentation:

const a = $.TypeVariable('a');
const b = $.TypeVariable('b');
const f = $.UnaryTypeVariable('f');

const map =
    def('map')
        ({ f: [Z.Functor] })
        ([$.Function ([a, b]), f (a), f (b)])
        (f => functor => functor.map(f));

const cur = map(x => x * 100) ([3, 4])

but I am getting the following error:

TypeError: ‘map’ applied ‘a -> b’ to the wrong number of arguments

map :: Functor f => (a -> b) -> f a -> f b
                     ^
                     1

Expected one argument but received three arguments:

  - 3
  - 0
  - [3, 4]

changing $.Function ([a, b]) to $.anyFunction makes the function work.

After two hours of trying to reason about the problem, I'm starting to wonder if i have done anything wrong or if it's just a bug. Thanks in advance

Avaq commented 5 years ago

It's not a bug. The type checker is telling you that your function f is being called in a way that is incompatible with its type definition. In particular, you defined it has taking exactly one argument (a), but your implementation is calling it with three arguments. The reason that happens is because Array.prototype.map calls the function with the item, the index, and the whole Array. You can get around it by wrapping f such that only one argument is passed down, or by using a custom map that doesn't supply any additional arguments to the mapper function.

hugonteifeh commented 5 years ago

Thanks a lot @Avaq , i missed this one.