【问题标题】:F# Fable and JS interop: unsafe list castingF# Fable 和 JS 互操作:不安全的列表转换
【发布时间】:2020-04-26 23:21:17
【问题描述】:

我不确定我是否在 Fable 的接口/编译器中发现了错误,或者我误用了类型系统/externs。

今天我遇到了一个非常令人沮丧的错误。像往常一样,我为我用 JS 编写的小函数键入了 extern,其中一个是从 NOSQL 数据库返回一个对象列表。显然寓言收到的对象不错。但是,当我尝试转换对象时,代码在没有任何错误或解释的情况下以不一致的方式死亡。

因为代码很复杂,包含 promise、解析和其他移动部分,我花了好几个小时才找出有罪的部分和原因,但最后我意识到 JS 数组与 F# 列表不匹配,这是我找到的唯一方法继续前进的内容如下:

type IJSInterface =
    abstract FetchPosts: string -> JS.Promise<DBPost list>

...

// Transform Javascript array to F# normal list
let postList = straightJSArrayWithTypedPosts |> List.toArray |> Array.toList

我的问题是:与 javascript 数组交互的推荐方式是什么?因为我阅读了所有我能阅读的文档,但我找不到关于这部分的任何精确说明。我个人认为它更像是一个错误。事实上,我希望我可以用编译器错误来禁止这个“功能”,或者在 javascript 和 F# 之间实现即时数组安全互操作。有这样的编译器选项吗?编译器怎么能避免让我在这些问题上花费整个星期天呢?有没有flag什么的?


编辑:正如答案中所猜测的,省略的 javascript 代码实际上返回了一个与 list 不同的 javascript array,尽管两者非常相似,尽管在大多数情况下表现相同,但它们并不相同在动态语言中

【问题讨论】:

    标签: f# fable-f#


    【解决方案1】:

    如果我正确理解了这个问题,那么问题是您的 JavaScript API 正在返回数组,但您希望将它们视为 F# 列表。

    Fable 中外部 API 的类型化工作方式是您必须定义类型“因为它是由外部 JavaScript API 生成的”。编译器不会进行任何转换,也不会尝试在运行时检查这一点,因此您只需要正确处理即可。如果您在实际 JavaScript API 生成数组的地方使用 list,那么您输入的外部库是错误的。

    所以,在这种情况下,我认为你应该使用:

    type IJSInterface =
        abstract FetchPosts: string -> JS.Promise<DBPost[]>
    

    这为您提供了不太好的 F# API,但在您调用 JavaScript 代码时这是意料之中的。

    【讨论】:

    • 感谢您的回答。我进行了测试并且它有效,所以我想将数组误认为列表是我的坏事,因为它们实际上不是同义词,这让我现在想把头撞在桌面上:昨天这个错误花了我这么多小时。我希望进行某种运行时检查,但编译器运行良好,运行时没有错误,除了实际上不起作用的东西。你在哪里找到的文档?我们可以强制编译器阻止这种安静的失败并执行运行时检查吗? (至少在直接的外部调用中?)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多