我正在尝试将 mocha 绑定(bind)写入 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
显然这里缺少一些东西。请帮忙。
最佳答案
PureScript 的外部函数接口(interface)其实很简单。例如,假设您有以下 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
那么我们从中可以理解什么呢?
IO
与 Eff e
类似,其中 e
是一排效果。 Unit
类似于 ()
。 print
函数具有 trace
效果,其类型为 Trace
。 print
函数可以与其他效果结合使用。行多态性。这意味着它是可组合的。 一个
Eff
值本身被称为一个 Action 。例如,类型为 print "Hello World!"
的 Eff (trace :: Trace | r) Unit
是一个 Action 。作为函数参数的
Eff
值称为处理程序。它可以被认为是一个没有参数的高阶有效函数。没有副作用的
Eff
值被称为纯值:type Pure a = forall e. Eff e a
runPure :: Pure a -> a
由于效果行(即
e
)是多态的(或者换句话说,是一个黑洞),PureScript 假设该函数没有副作用。然而,这也意味着它可以与其他有效的功能组合。Eff
monad 是程序员和编译器之间的契约,其中程序员向编译器 promise 给定的 Eff
值将仅具有规定的效果行,而没有更多。来到你的
describe
函数:其实这是错误的。您的
describe
函数确实将函数作为参数:describe(function(){
//do stuff
});
另外它所接受的函数没有参数,这意味着它是一个有效的函数。因此它必须是
Eff e a
类型,其中 e
和 a
可以分别是任何效果行和任何返回值。因此,您的 describe 函数必须是以下类型:
describe :: Eff e a -> Eff (describe :: Describe | e) {}
在 Haskell 中,它会这样写:
describe :: IO a -> IO ()
PureScript 只是比 Haskell 更明确。无论如何,
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!"
整个代码如下:
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:
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
};
}());
希望有帮助。
关于mocha.js - PureScript FFI 转 Mocha ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24728624/