Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .bowerrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"ignoredDependencies": [
"purescript-eff"
]
}
6 changes: 5 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"package.json"
],
"dependencies": {
"purescript-prelude": "^3.0.0"
"purescript-prelude": "^3.0.0",
"purescript-foldable-traversable": "^3.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should add this dependency here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me have a think about how we can avoid it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also feels a bit odd to me. But then so does putting it in purescript-foldable-traversable. Curious to read your idea.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option is to put a traverseRec/traverseRec_ into Foldable/Traversable, which would use MonadRec, and then to implement it for Array, List, etc., but that seems unpleasant for a bunch of reasons.

I'm going to think about how we might be able to create something general for consuming things one at a time without creating garbage.

Copy link
Contributor Author

@matthewleon matthewleon Jun 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes... Without running any benchmarks, my guess is that the tailRecEff machinery here would be significantly less efficient than this PR: https://github.com/purescript/purescript-tailrec/blob/master/src/Control/Monad/Rec/Class.purs

Generally speaking, having some kind of traverseRec seems nice. But I feel like for Eff in particular, it makes sense to have something optimized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought on traverseRec: separate typeclasses for it. That makes the change un/less breaking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that's the simplest approach. It's pretty imperative, but then so is Eff generally. Something specific to Eff like

class Functor f <= Iterable f where
  forEach_ :: forall eff a b. (a -> Eff eff b) -> f a -> Eff eff Unit
  forEach :: forall eff a b. (a -> Eff eff b) -> f a -> Eff eff (f b)

should provide a nice sweet spot between "too general, instances can't be made efficient" and "too specific, not enough instances".

},
"devDependencies": {
"purescript-console": "^3.0.0"
}
}
16 changes: 16 additions & 0 deletions src/Control/Monad/Eff.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,19 @@ exports.foreachE = function (as) {
};
};
};

exports.traverseEImpl = function (foldl) {
return function (xs) {
return function (f) {
var call = function() {
return function(x) {
f(x)();
};
};

return function () {
foldl(call)()(xs);
};
};
};
};
17 changes: 16 additions & 1 deletion src/Control/Monad/Eff.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Control.Monad.Eff
, Eff
, Pure
, runPure
, untilE, whileE, forE, foreachE
, untilE, whileE, forE, foreachE, traverseE
) where

import Control.Applicative (class Applicative, liftA1)
Expand All @@ -12,6 +12,7 @@ import Control.Bind (class Bind)
import Control.Monad (class Monad, ap)

import Data.Functor (class Functor)
import Data.Foldable (class Foldable, foldl)
import Data.Unit (Unit)

-- | The kind of all effect types.
Expand Down Expand Up @@ -87,3 +88,17 @@ foreign import forE :: forall e. Int -> Int -> (Int -> Eff e Unit) -> Eff e Unit
-- | `foreach xs f` runs the computation returned by the function `f` for each
-- | of the inputs `xs`.
foreign import foreachE :: forall e a. Array a -> (a -> Eff e Unit) -> Eff e Unit

-- | Loop over a Foldable collection of values.
-- |
-- | `traverseE xs f` runs the computation returned by the function `f` for each
-- | of the inputs `xs`.
traverseE :: forall e a f. Foldable f => f a -> (a -> Eff e Unit) -> Eff e Unit
traverseE = traverseEImpl foldl

foreign import traverseEImpl
:: forall e a f
. (forall b. (b -> a -> b) -> b -> f a -> b)
-> f a
-> (a -> Eff e Unit)
-> Eff e Unit
11 changes: 11 additions & 0 deletions test/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Test.Main where

import Prelude
import Control.Monad.Eff (Eff, foreachE, traverseE)
import Control.Monad.Eff.Console (CONSOLE, log)

main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = do
let foobar = ["foo", "bar", "bam"]
foreachE foobar log
traverseE foobar log