safareli/free

Add methods `or` and `and` for concurrency

Opened this issue · 11 comments

I was thinking what if instead of ignoring law <*> = ap make Free lawfull but add two methods or and and which could be used when actions should be resolved concurrently.

possibly change foldmap to somethink like this:

 -- don't  quite like the field names
type Interpreter i m a =
  { or   :: m c -> m c -> m  c
  , and  :: m c -> m b -> m (c, b)
  , fold :: i   -> m a
  , type :: TypeRep m -- we need to access `of` and `chainRec`.
  }

interpret :: (ChainRec m, Monad m) => Free i a ~> Interpreter i m a -> m a

we would need to change type of Free to:

data Free i a
-  = Ap { x: (Free i b), y: (Free i (b -> a)) }
+  = And { x: (Free i a), y: (Free i b) }
+  | Or { x: (Free i a), y: (Free i a) }
   | Pure { x: a }
   | Lift { x: i, f: (b -> a) }
   | Chain { x: (Free i b), f: (b -> (Free i a)) }

it would also change description of the repo

-Combination of a free applicative functor and free monad
+Free Monad with simple concurrency constructs

With this constructs we could also have this static methods on Free:

Free.concurrently :: [Free i a] -> Free i [a]
Free.race :: [Free i a] -> Free i a
Free.sequentially :: [Free i a] -> Free i [a]

@jdegoes I would love to hear your thoughts on this.

@safareli if you haven't seen it already, there's some discussion of concurrent free applicatives in section 5.4 of "There is no fork" http://dl.acm.org/citation.cfm?id=2628144
If Free is no longer a (concurrent) Applicative, it wouldn't be possible to use generic functions like lift with it, which would be a bit of a shame.

url is not working

(amended the link - from there, follow the link to the pdf)

If Free is no longer a (concurrent) Applicative, it wouldn't be possible to use generic functions like lift with it, which would be a bit of a shame.

Free is concurrent if target monad is not lawful. so if in perfect world all Task/Futures are lawful then there will be no concurrency benefits from dispatching to ap of target monad.

if we add some minimal concurrency constructs to Free and then it would be possible to still fold it concurrently when target monad is lawful.

related issue: fantasy-land#179

will take a look at that paper but haxl is not lawful as well

I like it. FWIW, or is often called race, and and is equivalent to a function normally called par. See purescript-parallel, for example.

MonadPar and MonadRace from purescript-parallel are what we need in JS will create an issue FL for that, thanks!

If we had that algebras in FL then foldMap would become:

foldMap :: (ChainRace m, ChainRec m, Monad m) => Free i a ~> (i -> m a) -> TypeRep m -> m a

And with something like Parallel we can transform (Monad m, ChainRace m) into just Applicative which is concurant (i.e. we would be able to use lift and general functions over Applicative while still be concurant)

Currently i'm porting the recent version of haskell-free-concurrent. Before I did not understood the implementation because of Lenses and it's strange operators, but now I did another try and i got it 🎉