PureScript FFI到摩卡

时间:2014-07-14 01:58:06

标签: mocha ffi purescript

我正在尝试将mocha绑定编写到PureScript中,我完全被Control.Monad.Eff

困惑
describe(function(){
  //do stuff  
});

Describe是一个不带任何东西并且返回IO或Eff或其他东西的函数(副作用没有返回值)。


到目前为止我的尝试

foreign import describe 
  "function describe(n){         \
  \ return function(){           \
  \   window.describe(n); \
  \ };                           \  
  \}" :: forall eff a. Eff eff a -> Eff eff

foreign import describe "describe" :: forall eff a. Eff eff a -> Eff eff
foreign import describe "describe" :: Eff -> Eff
foreign import describe "describe" :: forall eff a. (a -> Eff eff) -> Eff eff

在这里显然遗漏了一些东西。请帮忙。

1 个答案:

答案 0 :(得分:14)

PureScript的外部函数接口实际上非常简单。例如,假设您具有以下JavaScript函数:

function si(p) {
    return function (r) {
        return function (t) {
            return p * r * t / 100;
        };
    };
}

您可以按如下方式导入它:

foreign import si :: Number -> Number -> Number -> Number

您还可以按如下方式内联函数:

foreign import si
    "function si(p) {\
    \    return function (r) {\
    \        return function (t) {\
    \            return p * r * t / 100;\
    \        };\
    \    };\
    \}" :: Number -> Number -> Number -> Number

对于副作用,PureScript不使用IO monad。相反,它使用Eff monad。

根据我的理解,Eff monad与带有额外类型参数的IO monad相同:一行效果。

例如,在Haskell中,print函数具有以下类型:

print :: Show a => a -> IO ()

在PureScript中,print函数具有以下类型:

print :: Show a => a -> Eff (trace :: Trace | r) Unit

那么我们从中了解到什么呢?

  1. IOEff e类似,其中e是一系列效果。
  2. Unit()类似。
  3. print函数的trace效果属于Trace类型。
  4. 此外,print功能可以与其他效果组合使用。行多态性。这意味着它是可组合的。
  5. Eff值本身称为操作。例如,类型print "Hello World!"的{​​{1}}是一个操作。

    作为函数参数的Eff (trace :: Trace | r) Unit值称为处理程序。它可以被认为是一个没有参数的高阶有效函数。

    没有副作用的Eff值称为纯值:

    Eff

    由于效果行(即type Pure a = forall e. Eff e a runPure :: Pure a -> a )是多态的(或者换句话说是空的,黑洞),PureScript假定该函数没有副作用。然而,这也意味着它可以与其他有效的功能组合。

    e monad是程序员和编译器之间的契约,程序员在其中承诺给定的Eff值只有指定的效果行而不再有。


    来到您的Eff功能:

      

    Describe是一个不带任何东西并且返回IO或Eff或其他东西的函数(副作用没有返回值)。

    其实这是错误的。您的describe函数确实将函数作为参数:

    describe

    此外,它所采用的函数没有参数,这意味着它是一个有效的函数。因此,它必须是describe(function(){ //do stuff }); 类型,其中Eff e ae可以分别是任何效果行和任何返回值。

    因此,您的describe函数必须是以下类型:

    a

    在Haskell中,它将写成如下:

    describe :: Eff e a -> Eff (describe :: Describe | e) {}
    

    PureScript比Haskell更明确。无论如何,describe :: IO a -> IO () 是您创建的新效果类型,它将其与其他效果类型区分开来,例如Describe

    Trace

    然后您将导入foreign import data Describe :: ! ,如下所示:

    describe

    最后你可以按如下方式使用它:

    foreign import describe
        "function describe(f) {\
        \    return function () {\
        \        window.describe(f);\
        \    };\
        \}" :: forall e a. Eff e a -> Eff (describe :: Describe | e) {}
    

    整个代码如下:

    main = do
        describe $ print "Hello World!"
    

    它会生成以下JavaScript:

    module Main where
    
    import Control.Monad.Eff
    import Debug.Trace
    
    foreign import data Describe :: !
    
    foreign import describe
        "function describe(f) {\
        \    return function () {\
        \        window.describe(f);\
        \    };\
        \}" :: forall e a. Eff e a -> Eff (describe :: Describe | e) {}
    
    main = do
        describe $ print "Hello World!"
    

    希望有所帮助。