Search code examples
javascripttypesfunctional-programmingtype-signature

Are there any conventions for Haskell-like type signatures in Javascript


When I eventually stumbled upon Hoogle, the importance of type signatures immediately became clear to me. Instead of looking for ambiguous and imprecise function names, you just search for type signatures:

inc :: Number a => a -> a
map :: (a -> b) -> [a] -> [b]
head :: [a] -> a

Hoogle makes code reuse a first class affiar :) Since Javascript isn't a purely functional language, one quickly encounters problems. Given is this naive curry implementation:

function curry(n, f) {
    var args = Array.prototype.slice.call(arguments);
    if (typeof n === 'undefined')
        args[1] = f.length;
    if (n === args.length - 2)
        return f.apply(undefined, args.slice(2));
    return function() {
        return curry.apply(undefined, args.concat(Array.prototype.slice.call(arguments)));
    };
}

function add(a, b) { return a + b; }
var addC = curry(2, add);

addC(2)(3); // 5
addC(2, 3); // 5

How could the corresponding type signature look like?

Number -> ((a1, ..., aN) -> b) -> (a1 -> ... -> aN -> b)
| Number -> ((a1, ..., aN) -> b) -> ((a1, ..., aN) -> b) // ???

This is hideous and not the desired result. In purely functional languages functions always have exactly one parameter - in JavaScript any number.

Are there any conventions how impure language features in Javascript can be expressed with the type signature system of Haskell (I guess it is based on Hindley-Milner)? Is there a (standardized) adaptation to javascript?


Solution

  • Are there any conventions how impure language features in Javascript can be expressed with the type signature system of Haskell?

    This is more complex that you'd think. To illustrate:

    function f(a,b) { return a + b; }
    

    At the simplest case, this is Int -> Int -> Int. If you wanted to actually cater for + working for strings, you'd need something like:

    Addable a => a -> a -> a
    

    But hey! - you would shout - in JS we can add numbers to strings as well! (at this point you need MultiParamTypeClasses which is a Haskell extension)

    Addable a b => a -> b -> a
    

    Perfect. Now we only have to implement Addable String String, Addable Int Int and Addable String Int. See how much you need, and we haven't even touched impure functions yet!

    When you introduce this, you pretty much introduce State. And since every function can throw, you need MonadError as well. And then they all have IO (console.log) available, right?

    For that pretty much every function in JS would need to be marked as RWST IO, kind of defeating the purpose of monadic signatures.

    I got here two years later and thought I could spell out the actual signature this would produce: Note that Addable would probably need to be able to add two distinct types to another, third type to fulfill all current JS behaviour. You'd also need to specify R, W, and S.

    forall a b c m. (MonadError m, MonadIO m, Addable a b c) => a -> b -> RWST R W S m c


    You see, Haskell is powerful enough to express side effects as static signatures. Other languages, such as Idris, can also do so, but in a slightly different way. However, it comes at a great expense: every function is now limited to only do what's in its signature.

    On the other hand, one of JS' biggest strengths lies in its dynamic nature. The fact that you can write a very complex data operation very easily:

    function f(a) {
        console.log(a + this.b);
        this.c(function() {
             setTimeout(console.log(a), 100);
        });
    }
    

    Is a huge benefit. Writing a signature for that in Haskell would take ages and would be meaningless if you rewrote it five minutes later.

    Sadly, I think that what you're asking for won't happen very soon. To clarify, I strictly mean a type system as powerful as what Haskell has, combined with the elastic and fast prototyping of JS (or Lua, which is similar but better in my opinion). To not sound overly pessimistic, pluggable type systems are being researched and hopefully we'll see more languages utilizing them in the future.

    <opinion>I can't see any of the javalike JS addons, including horrible ES6 class, being even remotely competitive for that, though.</opinion>