使用purescript的FFI

时间:2015-07-22 12:58:40

标签: ffi purescript

我试图从purescript调用navigator.geolocation.getCurrentPosition javascript函数,但我遇到了两个问题。

在javascript中,它会使用类似

的东西来调用
navigator.geolocation.getCurrentPosition(function(position) { ... });

其中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 个答案:

答案 0 :(得分:7)

  

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

您已将回复类型正确识别为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等类型,以更加可组合的方式包装您的函数。

您可能希望阅读how to use the Eff monad上的文章。