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
那么我们从中理解了什么?
-
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
};
}());
希望对您有所帮助。