在Javascript中是否有类似Haskell类型签名的约定

时间:2015-11-17 21:44:01

标签: javascript types functional-programming type-signature

当我最终偶然发现Hoogle时,类型签名的重要性立即变得清晰。您只需搜索类型签名:

,而不是查找含糊不清且不精确的函数名称
inc :: Number a => a -> a
map :: (a -> b) -> [a] -> [b]
head :: [a] -> a

Hoogle使代码重用成为一流的affiar :)由于Javascript不是纯函数式语言,因此很快就会遇到问题。鉴于这种天真的咖喱实施:

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

相应的类型签名怎么样?

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

这很可怕而不是理想的结果。在纯函数式语言中,函数总是只有一个参数 - 在JavaScript中任意数字。

是否有任何约定如何使用Haskell的类型签名系统表达Javascript中不纯的语言功能(我猜它是基于Hindley-Milner)?是否有(标准化)适应javascript?

1 个答案:

答案 0 :(得分:3)

  

是否有任何约定如何使用Haskell的类型签名系统表达Javascript中不纯的语言特性?

你认为这更复杂。举例说明:

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

在最简单的情况下,这是Int -> Int -> Int。如果你想真正满足+为字符串工作,你需要像:

Addable a => a -> a -> a

但是嘿! - 你会喊 - 在JS我们也可以为字符串添加数字! (此时你需要MultiParamTypeClasses这是一个Haskell扩展名)

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

完美。现在我们只需实施Addable String StringAddable Int IntAddable String Int。看看你需要多少,我们甚至还没有触及不纯的功能!

当您介绍this时,您几乎会介绍State。由于每个函数都可以throw,因此您还需要MonadError。然后他们都有IOconsole.log)可用,对吧?

对于那个,JS中的每个函数都需要被标记为RWST IO,这有点打败了monadic签名的目的。

  

两年后我来到这里,并认为我可以拼出这将产生的实际签名:   请注意,Addable可能需要能够将两种不同的类型添加到另一种类型,第三种类型以满足所有当前的JS行为。您还需要指定RWS

     

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

你知道,Haskell足以表达作为静态签名的副作用。其他语言,如伊德里斯,也可以这样做,但方式略有不同。但是,这需要付出很大的代价:现在每个功能都只限于其签名中的内容。

另一方面,JS最大的优势之一在于其动态性。您可以非常轻松地编写非常复杂的数据操作:

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

是一个巨大的好处。在Haskell中为此写一个签名需要很长时间,如果你在五分钟后重写它将毫无意义。

可悲的是,我认为你要求的东西不会很快发生。为了澄清,我严格意味着一个像Haskell一样强大的类型系统,结合JS(或Lua的弹性和快速原型设计,在我看来类似但更好)。为了不听起来过于悲观,可插拔类型的系统正在研究中,希望我们将来会看到更多使用它们的语言。

<opinion>我看不到任何javalike JS插件,包括可怕的ES6 class,甚至可以远程竞争。</opinion>