使用Purescript的FFI调用带有回调函数的js函数

3

我想在 Purescript 中调用 navigator.geolocation.getCurrentPosition JavaScript 函数,但是我遇到了两个问题。

在 JavaScript 中,可以使用如下代码进行调用:

navigator.geolocation.getCurrentPosition(function(position) { ... });

位置是一个对象。

首先,我不知道返回类型应该是什么,因为它不返回任何内容,而是调用回调函数。

其次,我不知道用什么类型来使用回调函数,因为该函数不能是纯函数,因为它的结果不会被返回。

到目前为止,我的翻译如下:

foreign import geolookup "function (callback) {\
        navigator.geolocation.getCurrentPosition(callback);
    \}" :: forall eff a. Eff (geolookup :: GeoLookup | eff) {}

geolookup \position -> ...

所以这里我的外部函数类型签名是forall eff a. Eff (geolookup :: GeoLookup | eff) {},但我知道在Eff之前也应该有一个回调参数。我只是不确定如何编写类型签名或实现它。

1个回答

8
首先,我不知道返回类型应该是什么,因为它不返回任何内容,而是调用回调函数。
你已经正确地将返回类型识别为Unit或{},但geolookup函数本身具有效果,因此应该用Eff类型构造函数进行包装。
其次,我不知道回调要使用什么类型,因为该函数不能是纯的,因为它的结果不会被返回。
因此,让我们给回调一个适当的类型。作为一种具有效果的函数,类似于a -> Eff _ b的东西是有意义的,并且为了避免在行中重复标签,我们被迫在我们的行中包含GeoLookup效果。因此,让我们给回调类型Position -> Eff (geolookup :: GeoLookup | eff) Unit。
然后我们的函数的完整类型变成了:
foreign import data Position :: *

geolookup :: forall eff. (Position -> Eff (geolookup :: GeoLookup | eff) Unit) ->
                         Eff (geolookup :: GeoLookup | eff) Unit

在 FFI 中,我们可以包装 navigator.geolocation.getCurrentPosition 调用以与此类型兼容。使用 0.7 编译器的 FFI 风格:
exports.geolookup = function(callback) {
  return function() { // Outer Eff
    navigator.geolocation.getCurrentPosition(function(p) {
      callback(p)(); // Extra () due to inner Eff
    });
  };
};

此时,您可能希望探索像ContTAff这样的类型,以更可组合地封装您的函数。

您可能会喜欢阅读有关如何使用 Eff Monad的文章。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接