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
モナドを利用します。
私が理解していることから、モナドは追加の型パラメータを持つモナドとEff
同じです: 効果の列です。IO
たとえば、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
モナドは、プログラマーとコンパイラーの間の契約であり、プログラマーはコンパイラーに対して、指定された値は指定された行の効果のみを持ち、それ以上は持たないことを約束しますEff
。
あなたの機能に来ますdescribe
:
Describe は何も取らずに IO や Eff などを返す関数です (副作用が発生して値が返されません)。
実はこれは間違っています。あなたの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
};
}());
それが役立つことを願っています。