【问题标题】:Polymorphic Anonymous Functions Type Aliases多态匿名函数类型别名
【发布时间】:2016-08-08 23:57:20
【问题描述】:

命名function() 语法与匿名函数语法的类型声明之间似乎存在细微差别:

type F<X, Y> = (x: X) => Y

// works:
function apply<X, Y>(f: F<X, Y>, x: X) : Y {
    return f(x)
}

// works:
const apply0 : <X, Y>(f: F, x: X) => Y = (f, x) => f(x)

// doesn't work
const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)

Flow console snippet

我需要从匿名 apply 函数的参数中对类型 F&lt;X, Y&gt; 的任何引用中删除泛型类型注释,以便类型检查器工作。

这是违反直觉的。

[编辑:] 但 Flow 似乎能够输入检查 apply1 调用,即使它无法输入检查 apply1 本身:

apply1(x => x * 2, 'a') // error: ^ string. This type is incompatible with
apply1(x => x * 2, 1) // works

更笼统地说:

// works:
type Apply<X, Y> = <X, Y>(f: F, x: X) => Y

const apply : Apply = (f, x) => f(x)    


// doesn't work:
type Apply1<X, Y> = <X, Y>(f: F<X, Y>, x: X) => Y

const apply1 : Apply1 = (f, x) => f(x)

Flow console snippet

我必须从类型别名 Apply 的参数中删除泛型类型注释 X, Y,以便 Flow 对其进行类型检查。

这是预期的行为还是我错过了什么?

【问题讨论】:

  • 我不使用 Flow,也不是最熟悉泛型类型,但似乎所有 XY 都应该分别对齐。此外,考虑到您的 Apply 类型确实有效,这个定义似乎应该失败:var res: String = apply((val) =&gt; 123, "abc"),但它通过了。
  • 你说得对。正确键入检查的唯一定义apply(x =&gt; x * 2, 'a') 是命名函数版本。
  • 我认为参数f: F 必须被视为f: F&lt;Any, Any&gt; 其中Any 是Flow 用来表示any 可能类型的任何内容。即使这样编译:var res: String = apply((val: Boolean) =&gt; 123, "abc")。可能需要提交报告。
  • 我不确定 Flow 是基于哪种类型系统,但我猜这个问题与方差有关。
  • 即使我们定义了显式类型Apply&lt;String, Number&gt;,然后将字符串以外的东西传递给apply()的第二个参数it compiles。 ...但后来我正在修补一个我实际上还没有学过的类型系统,所以谁知道呢。帮我个忙,如果您有解决办法,请在此处留言。我很想知道结果如何。

标签: javascript flowtype


【解决方案1】:

TL;DR:试试

const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)

说明

首先,正如@squint 在评论中提到的那样,不带类型参数的F 隐含地表示F&lt;any, any&gt;,这就是apply0 在您的示例中起作用的原因。

那么为什么你的apply1 有错误呢?嗯,这是因为 Flow 不推断泛型。所以当你写的时候

const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = (f, x) => f(x)

作业的右边是

(f, x) => f(x)

Flow 无法推断出这个箭头函数是多态的。所以你可以像这样向 RHS 添加类型参数:

const apply1 : <X, Y>(f: F<X, Y>, x: X) => Y = <X, Y>(f: F<X, Y>, x: X): Y => f(x)

这应该可以解决错误。但此时,左侧的类型注解就不再需要了。所以你可以把它简化为

const apply1 = <X, Y>(f: F<X, Y>, x: X): Y => f(x)

进一步阅读

Avik Chaudhuri 在similar stack overflow question 上写了一个简短的解释,然后链接到similar answer on GitHub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 2019-10-08
    • 2014-05-29
    • 2021-12-12
    相关资源
    最近更新 更多