safareli / free

Combination of a free applicative functor and free monad
MIT License
57 stars 3 forks source link

Add methods `or` and `and` for concurrency #27

Open safareli opened 7 years ago

safareli commented 7 years ago

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]
safareli commented 7 years ago

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

kwijibo commented 7 years ago

@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.

safareli commented 7 years ago

url is not working

kwijibo commented 7 years ago

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

safareli commented 7 years ago

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

safareli commented 7 years ago

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

jdegoes commented 7 years ago

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

safareli commented 7 years ago

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

safareli commented 7 years ago

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)

safareli commented 7 years ago

Also related: SeqPar - Free applicative in free monad

safareli commented 7 years ago

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 🎉