使用purescript的FFI使用回调调用js函数

Jim*_*ies 1 ffi purescript

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

在javascript中,它将使用类似的东西调用

navigator.geolocation.getCurrentPosition(function(position) { ... });
Run Code Online (Sandbox Code Playgroud)

其中position是一个对象.

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

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

到目前为止我有

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

geolookup \position -> ...
Run Code Online (Sandbox Code Playgroud)

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

Phi*_*man 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
Run Code Online (Sandbox Code Playgroud)

在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
    });
  };
};
Run Code Online (Sandbox Code Playgroud)

此时,您可能希望查看类似的类型ContTAff以更可组合的方式包装您的函数.

您可能希望阅读有关如何使用Eff monad的文章.