12

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

ここには明らかに何かが欠けています。助けてください。

4

1 に答える 1

14

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

では、このことから何がわかるでしょうか。

  1. IO効果の行がEff eどこにあるかに似ています。e
  2. Unitに似てい()ます。
  3. print関数には、タイプの効果traceがありTraceます。
  4. さらに、この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
    };
}());

それが役立つことを願っています。

于 2014-07-14T04:31:39.377 に答える