【问题标题】:How do I use an unwrapped polymorphic variant [union type] in a type parameter?如何在类型参数中使用展开的多态变体 [联合类型]?
【发布时间】:2020-11-28 22:18:58
【问题描述】:

目标:绑定到Service Worker Cache

我正在编写一个绑定,让我在 ReScript 中编写 Service Worker。字符串 URL 和 Requests 有时可以互换使用。

在可能的情况下,我会避免 JS 输出中的噪音。

我对@9​​87654323@的了解

我知道我可以像这样使用[@bs.unwrap]add 方法编写绑定

[@bs.send]
  external add: (cache, [@bs.unwrap] [ `Request(Request.t) | `String(string)])
  => Js.Promise.t(unit) = "add";

这是一个简单的用法。

问题:与请求和/或字符串的array 绑定

然而,addAll 方法具有更复杂的类型签名。它需要一个对象数组,可以是数组或请求,也可以是字符串数组或同时具有这两种类型的项的数组。

但据我所知,您不能在类型参数中拆箱类型,例如

[@bs.send]
  external addAll: (cache,
   array([@bs.unwrap] [ `Request(Request.t) | `String(string)])
  => Js.Promise.t(unit) = "addAll";

问题:这种绑定可以在 ReScript 中建模吗?

当然,放弃字符串大小写并使用 Requests 或编写两个单独的绑定并假设我不需要同时具有两者的数组是合理的。

但现在我只是好奇:有没有办法在 ReScript 的绑定中对这种类型的类型进行建模?

【问题讨论】:

    标签: interop ffi reason bucklescript rescript


    【解决方案1】:

    您可以使用抽象类型和一组转换函数将值“转换”为该类型,而不是多态变体:

    module Value = {
      type t;
      external request: Request.t => t = "%identity";
      external str: string => t = "%identity";
    };
    
    [@bs.send]
      external addAll: (cache, array(Value.t)) => Js.Promise.t(unit) = "addAll";
    

    示例用法:

    addAll(cache, [|
      Value.request(req),
      Value.str("foo"),
    |])
    

    或为简洁起见使用本地打开:

    addAll(cache, Value.[|
      request(req),
      str("foo"),
    |])
    

    这也是Js.Json 编码器的工作方式,如果您想知道的话。而且由于Js.Json 也有解码器,因此您知道如果需要,也可以采用其他方式。这样做有点复杂,并且取决于已抽象出来的底层类型。

    顺便说一句,这是from my BuckleScript cookbook,它还有很多其他食谱可能会在这种棘手的情况下派上用场。

    【讨论】:

      猜你喜欢
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多