javascriptfunctional-programmingsanctuaryfantasylandfolktale

fantasy-land confusion on ap method signature


In fantasy-land spec, the signature for ap method is defined as

fantasy-land/ap :: Apply f => f a ~> f (a -> b) -> f b

This translates as: The container f with value a has a method ap which takes a parameter container f with value of a function (a ->b) and returns a container f with value b. I hope I am right in this interpretation.

If I test this with Folktale, However I see different results:

const Maybe = require("data.maybe")
Maybe.of(5).ap(Maybe.of(x => x + 1)) // Uncaught TypeError: f is not a function
Maybe.of(x=>x+1).ap(Maybe.of(5))     // Maybe { value: 6 }
Maybe.of(x=>x+1).ap(Either.of(5))    // Either { value: 6 }

If I test this with Sanctuary, I see similar results (though Sanctuary does not have it as a "method")

const S = require("sanctuary")
let a = S.of(S.Maybe)(5)
let fn = S.of(S.Maybe)(x => x + 1)
S.ap(fn)(a) // Just (6)
S.ap(a)(fn) // Uncaught TypeError: Invalid value

This brings me to the conclusion that perhaps the fantasy-land specs for ap method could be:

fantasy-land/ap :: Apply f => f (a -> b) ~> f a -> f b

I am a newbie on FP and fantasy-land as well. I am happy to get corrected :)


Solution

  • Fantasyland specifies an interoperability layer, not a public API (although it use to be the case), hence the fantasy-land/ prefix which would otherwise not be user friendly at all. As a result you can find different conventions in different libraries. Oftentimes libraries implement both ap and fantasy-land/ap, with the arguments flipped.

    The specification for ap also changed at some point. Some articles still mention the old spec. As for implementations, they don't want to break their users and the old spec is arguably easier to use (you can chain ap calls).