Skip to content

Commit

Permalink
Use same representation as Eff
Browse files Browse the repository at this point in the history
  • Loading branch information
safareli committed Dec 13, 2017
1 parent ad5675e commit c5a83e3
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 79 deletions.
8 changes: 1 addition & 7 deletions bench/Bench/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,9 @@ extended = do
log header
bench2 ">>=R" testBindRight testBindRight [20000, 50000, 100000, 1000000]
bench2 ">>=L" testBindLeft testBindLeft [20000, 50000, 100000, 1000000]
bench2 "map" testMap testMap [10000, 20000, 50000, 100000, 1000000]
timed ["map", "Ef", "10000000"] $ testMap 10000000 -- Aff can't handle this number, I got `JavaScript heap out of memory`
bench2 "map" testMap testMap [10000, 20000, 50000, 100000, 1000000, 350000, 700000]
bench2 "apply" testApply testApply [10000, 20000, 50000, 100000, 1000000]

timed :: Array String -> Ef BenchEff Unit -> Eff BenchEff Unit
timed msg ef = do
let eff = liftEf ef
logBench' msg $ benchWith' 5 \_ -> unsafePerformEff eff

header :: String
header =
"| bench | type | n | mean | stddev | min | max |\n" <>
Expand Down
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
],
"dependencies": {
"purescript-prelude": "^3.0.0",
"purescript-eff": "^3.1.0"
"purescript-eff": "^3.1.0",
"purescript-unsafe-coerce": "^3.0.0"
},
"devDependencies": {
"purescript-foldable-traversable": "^3.6.1",
Expand Down
108 changes: 51 additions & 57 deletions src/Control/Monad/Ff.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use strict";


// Ef a
// Ef a
// = () -> a
// | { tag: "PURE", _0 :: a, _1 :: Void }
// | { tag: "MAP", _0 :: b -> a, _1 :: Ef b }
// | { tag: "APPLY", _0 :: Ef b, _1 :: Ef (b -> a) }
// | { tag: "BIND", _0 :: b -> Ef a, _1 :: Ef b }
// | { Ef a, tag: "PURE", _0 :: a, _1 :: Void }
// | { Ef a, tag: "MAP", _0 :: b -> a, _1 :: Ef b }
// | { Ef a, tag: "APPLY", _0 :: Ef b, _1 :: Ef (b -> a) }
// | { Ef a, tag: "BIND", _0 :: b -> Ef a, _1 :: Ef b }

// Operation a b
// = { tag: "MAP", _0 :: a -> b }
Expand All @@ -15,84 +15,78 @@
// | { tag: "BIND", _0 :: a -> Ef b }


function Ef(tag, _0, _1) {
this.tag = tag;
this._0 = _0;
this._1 = _1;
}

var PURE = "PURE";
var MAP = "MAP";
var APPLY = "APPLY";
var BIND = "BIND";
var APPLY_FUNC = "APPLY_FUNC";

exports.liftEffE = function (eff) {
return eff;
};

exports.pureE = function (x) {
return new Ef(PURE, x);
return mkEf(PURE, x);
};

exports.mapE = function (f) {
return function (eff) {
return new Ef(MAP, f, eff);
return mkEf(MAP, f, eff);
};
};

exports.applyE = function (effF) {
return function (eff) {
return new Ef(APPLY, eff, effF);
return mkEf(APPLY, eff, effF);
};
};

exports.bindE = function (eff) {
return function (f) {
return new Ef(BIND, f, eff);
return mkEf(BIND, f, eff);
};
};

exports.toEff = function (inputEff) {
if (typeof inputEff === "function") {
return inputEff;
}
return function() {
var operations = [];
var eff = inputEff;
var res;
var op;
var tag;
effLoop: for (;;) {
tag = eff.tag;
if (tag !== undefined) {
if (tag === MAP || tag === BIND || tag === APPLY) {
operations.push(eff);
eff = eff._1;
continue;
}
// here `tag === PURE`
res = eff._0;
} else {
// here `typeof eff == "function"`
res = eff();

var mkEf = function (tag, _0, _1) {
var eff = function eff_() { return toEff(eff_) }
eff.tag = tag
eff._0 = _0
eff._1 = _1
return eff
}

var toEff = function (inputEff) {
var operations = [];
var eff = inputEff;
var res;
var op;
var tag;
effLoop: for (;;) {
tag = eff.tag;
if (tag !== undefined) {
if (tag === MAP || tag === BIND || tag === APPLY) {
operations.push(eff);
eff = eff._1;
continue;
}
// here `tag === PURE`
res = eff._0;
} else {
// here `typeof eff == "function"`
res = eff();
}

while ((op = operations.pop())) {
if (op.tag === MAP) {
res = op._0(res);
} else if (op.tag === APPLY_FUNC) {
res = op._0(res);
} else if (op.tag === APPLY) {
eff = op._0;
operations.push(new Ef(APPLY_FUNC, res));
continue effLoop;
} else { // op.tag === BIND
eff = op._0(res);
continue effLoop;
}
while ((op = operations.pop())) {
if (op.tag === MAP) {
res = op._0(res);
} else if (op.tag === APPLY_FUNC) {
res = op._0(res);
} else if (op.tag === APPLY) {
eff = op._0;
operations.push(new Ef(APPLY_FUNC, res));
continue effLoop;
} else { // op.tag === BIND
eff = op._0(res);
continue effLoop;
}
return res;
}
};
return res;
}
};
11 changes: 3 additions & 8 deletions src/Control/Monad/Ff.purs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
module Control.Monad.Ef
( Ef
, toEff
) where
module Control.Monad.Ef (Ef) where

import Control.Applicative (class Applicative)
-- import Control.Applicative (class Applicative, liftA1)
Expand All @@ -12,6 +9,7 @@ import Control.Monad (class Monad)
import Control.Monad.Eff (Eff, kind Effect)
import Data.Functor (class Functor)
import Control.Monad.Eff.Class (class MonadEff)
import Unsafe.Coerce (unsafeCoerce)


foreign import data Ef :: # Effect -> Type -> Type
Expand All @@ -33,11 +31,8 @@ instance bindEf :: Bind (Ef e) where
instance monadEf :: Monad (Ef e)

instance monadEEFff :: MonadEff eff (Ef eff) where
liftEff = liftEffE
liftEff = unsafeCoerce

foreign import toEff :: forall e a. Ef e a -> Eff e a

foreign import liftEffE :: forall e a. Eff e a -> Ef e a
foreign import mapE :: forall e a b. (a -> b) -> Ef e a -> Ef e b
foreign import applyE :: forall e a b. Ef e (a -> b) -> Ef e a-> Ef e b
foreign import pureE :: forall e a. a -> Ef e a
Expand Down
10 changes: 7 additions & 3 deletions src/Control/Monad/Ff/Class.purs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
module Control.Monad.Ef.Class where
module Control.Monad.Ef.Class
( class MonadEf
, liftEf
) where

import Control.Category (id)
import Control.Monad (class Monad)
import Control.Monad.Ef (Ef, toEff)
import Control.Monad.Ef (Ef)
import Control.Monad.Eff (Eff)
import Unsafe.Coerce (unsafeCoerce)

class Monad m <= MonadEf eff m | m -> eff where
liftEf :: forall a. Ef eff a -> m a
Expand All @@ -12,4 +16,4 @@ instance monadEfEf :: MonadEf eff (Ef eff) where
liftEf = id

instance monadEfEff :: MonadEf eff (Eff eff) where
liftEf = toEff
liftEf = unsafeCoerce
3 changes: 0 additions & 3 deletions test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import Control.Apply (lift2)
import Control.Monad.Eff.Class (class MonadEff, liftEff)
import Control.Monad.Ef (Ef)
import Control.Monad.Ef.Class (liftEf)
import Data.Traversable (for_)
import Performance.Minibench (benchWith)
import Control.Monad.Eff.Unsafe (unsafePerformEff)
import Control.Monad.Eff.Console (CONSOLE)


Expand Down

0 comments on commit c5a83e3

Please sign in to comment.