3

我正在尝试navigator.geolocation.getCurrentPosition从 purescript 调用 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 之前也应该有一个回调参数。我只是不确定如何编写类型签名或实现它。

4

1 回答 1

8

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

您已正确地将返回类型标识为Unit, 或{},但geolookup函数本身是有效的,因此应使用Eff类型构造函数进行包装。

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

所以让我们给回调一个合适的类型。作为一个有效的函数,类似的东西a -> Eff _ b是有意义的,为了避免行中的重复标签,我们被迫GeoLookup在我们的行中包含这个效果。所以让我们给回调 type 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的文章。

于 2015-07-22T17:39:12.600 回答