我正试图将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很明显这里漏掉了什么。请帮帮忙。
发布于 2014-07-14 04:31:39
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单曲。相反,它使用了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值本身称为操作。例如,类型为print "Hello World!"的Eff (trace :: Trace | r) Unit是一个动作。
函数的参数Eff值称为处理程序。它可以看作是一种无参数的高阶有效函数.
没有副作用的Eff值称为纯值:
type Pure a = forall e. Eff e a
runPure :: Pure a -> a由于行效应(即e)是多态的(或者换句话说是空的,黑洞),PureScript假定该函数没有副作用。然而,它也意味着它可以与其他有效的功能组成。
Eff monad是程序员和编译器之间的一种契约,程序员在该契约中向编译器保证,给定的Eff值将只具有指定的效果行,并且不会有更多的效果。
使用您的describe函数:
Describe是一个函数,它不需要任何信息并返回IO,或者Eff或者其他什么意思(副作用发生了,没有返回值)。
其实这是不对的。您的describe函数确实使用一个函数作为参数:
describe(function(){
//do stuff
});此外,它所使用的函数没有参数,这意味着它是一个有效的函数。因此,它必须是Eff e a类型,其中e和a可以分别是任何效果行和任何返回值。
因此,您的描述函数必须是以下类型:
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
};
}());希望这能有所帮助。
https://stackoverflow.com/questions/24728624
复制相似问题