首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PureScript FFI to mocha

PureScript FFI to mocha
EN

Stack Overflow用户
提问于 2014-07-14 01:58:06
回答 1查看 828关注 0票数 12

我正试图将mocha绑定写到PureScript中,并且对Control.Monad.Eff完全感到困惑。

代码语言:javascript
复制
describe(function(){
  //do stuff  
});

Describe是一个函数,它不需要任何信息并返回IO,或者Eff或者其他什么意思(副作用发生了,没有返回值)。

到目前为止我的尝试

代码语言:javascript
复制
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

很明显这里漏掉了什么。请帮帮忙。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-07-14 04:31:39

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

代码语言:javascript
复制
function si(p) {
    return function (r) {
        return function (t) {
            return p * r * t / 100;
        };
    };
}

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

代码语言:javascript
复制
foreign import si :: Number -> Number -> Number -> Number

您还可以将该函数内联如下:

代码语言:javascript
复制
foreign import si
    "function si(p) {\
    \    return function (r) {\
    \        return function (t) {\
    \            return p * r * t / 100;\
    \        };\
    \    };\
    \}" :: Number -> Number -> Number -> Number

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

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

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

代码语言:javascript
复制
print :: Show a => a -> IO ()

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

代码语言:javascript
复制
print :: Show a => a -> Eff (trace :: Trace | r) Unit

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

  1. IO类似于Eff e,其中e是一行效果。
  2. Unit类似于()
  3. print函数具有trace效果,其类型为Trace
  4. 此外,print函数还可以与其他效果相结合。行多态这意味着它是可合成的。

Eff值本身称为操作。例如,类型为print "Hello World!"Eff (trace :: Trace | r) Unit是一个动作。

函数的参数Eff值称为处理程序。它可以看作是一种无参数的高阶有效函数.

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

代码语言:javascript
复制
type Pure a = forall e. Eff e a
runPure :: Pure a -> a

由于行效应(即e)是多态的(或者换句话说是空的,黑洞),PureScript假定该函数没有副作用。然而,它也意味着它可以与其他有效的功能组成。

Eff monad是程序员和编译器之间的一种契约,程序员在该契约中向编译器保证,给定的Eff值将只具有指定的效果行,并且不会有更多的效果。

使用您的describe函数:

Describe是一个函数,它不需要任何信息并返回IO,或者Eff或者其他什么意思(副作用发生了,没有返回值)。

其实这是不对的。您的describe函数确实使用一个函数作为参数:

代码语言:javascript
复制
describe(function(){
  //do stuff
});

此外,它所使用的函数没有参数,这意味着它是一个有效的函数。因此,它必须是Eff e a类型,其中ea可以分别是任何效果行和任何返回值。

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

代码语言:javascript
复制
describe :: Eff e a -> Eff (describe :: Describe | e) {}

在Haskell,它将写成如下:

代码语言:javascript
复制
describe :: IO a -> IO ()

PureScript只是比Haskell更明确。无论如何,Describe是您创建的一种新的效果类型,它将它与其他效果类型(如Trace )区别开来。

代码语言:javascript
复制
foreign import data Describe :: !

然后导入describe,如下所示:

代码语言:javascript
复制
foreign import describe
    "function describe(f) {\
    \    return function () {\
    \        window.describe(f);\
    \    };\
    \}" :: forall e a. Eff e a -> Eff (describe :: Describe | e) {}

最后,您可以如下所示使用它:

代码语言:javascript
复制
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!"

它将产生以下JavaScript:

代码语言:javascript
复制
var PS = PS || {};

PS.Main = (function () {
    "use strict";

    var Prelude = PS.Prelude;
    var Debug_Trace = PS.Debug_Trace;

    function describe(f) {
        return function () {
            window.describe(f);
        };
    }

    var print = Debug_Trace.print(Prelude.showString({})); 

    var main = describe(print("Hello World!"));

    return {
        main: main, 
        describe: describe
    };
}());

希望这能有所帮助。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24728624

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档