Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spec for Pearing of Monad and Applicative #186

Open
safareli opened this issue Oct 20, 2016 · 6 comments
Open

Add spec for Pearing of Monad and Applicative #186

safareli opened this issue Oct 20, 2016 · 6 comments

Comments

@safareli
Copy link
Member

safareli commented Oct 20, 2016

in purescript-parallel there are this classes:

-- | The `MonadPar` class abstracts over monads which support some notion of
-- | parallel composition.
-- |
-- | The `unit` and `par` functions should correspond to `pure` and `lift2` for
-- | some valid `Applicative` instance, but that instance need not arise from
-- | the underlying `Monad`.
class Monad m <= MonadPar m where
  par :: forall a b c. (a -> b -> c) -> m a -> m b -> m c

-- | The `MonadRace` class extends `MonadPar` to those monads which can be
-- | _raced_. That is, monads for which two computations can be executed in parallel
-- | returning the result from the computation which finishes first.
-- |
-- | The `stall` and `race` functions should satisfy the `Alternative` laws.
class MonadPar m <= MonadRace m where
  stall :: forall a. m a
  race :: forall a. m a -> m a -> m a

I think we should add them to fantasy land spec so that different implementations of Future/Task could implement them consistently such that libs like @safareli/Free and @DrBoolean/freeky could depend on them.

If we had this algebras we can also port Parallel using which we can transform any (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) which is awasome!

I think we should name use this names as they dont need structure to be a monad:

  • ChainPar for MonadPar
  • ChainRace for MonadRace

realted issues:

@safareli safareli changed the title add ChainRace and ChainPar spec Add spec for Chain which could support some notion of parallel composition Oct 20, 2016
@safareli
Copy link
Member Author

safareli commented Oct 20, 2016

Just came across purescript-parallel#10 in which MonadRace and MonadPar are removed in favor of:

-- | The `Parallel` class abstracts over monads which support
-- | parallel composition via some related `Applicative`.
class (Monad m, Applicative f) <= Parallel f m | m -> f, f -> m where 
  parallel   :: m ~> f
  sequential :: f ~> m

Functional dependencies is used in type signature

With that in mind we need a way to convert a Monadic value to corresponding Applicative and Applicative to corresponding Monad.

M.parallel   :: M  a -> Ap a
M.sequential :: Ap a -> M  a
M.sequential(
  M.parallel(M.of(1)).ap(M.parallel(M.of(id)))
)

But I don't quite see how should we express that relation between Monad and Applicative in FL.

We would need to also define Alternative (#187) so we still have race (with name alt)

@safareli
Copy link
Member Author

safareli commented Oct 24, 2016

Example for Task would look like this:

// Http.get :: URL -> Task HttpErr Response
Task.sequential(
  lift2(
    (p1 =>p2=> [p1, p2]),
    Task.parallel(Http.get('/page1')),
    Task.parallel(Http.get('/page2'))
  )
).chain([p1, p2] => Http.get(getPageFromTwoPage(p1, p2)))

it's not that nice, but we can actually define them as instance methods which look better:

lift2(
  (p1 =>p2=> [p1, p2]),
  Http.get('/page1').parallel(),
  Http.get('/page2').parallel()
).sequential().chain([p1, p2] => Http.get(getPageFromTwoPage(p1, p2)))

The law would be: m.parallel().sequential() is equivalent to m

@safareli
Copy link
Member Author

safareli commented Oct 24, 2016

@rpominov @robotlolita @Avaq @SimonRichardson what do you think on this?

It will solve issue related to <*> = ap so if a monad supports some notion of parallelism it would have method parallel which will return same computation as non Monadic Applicative and all operations on it could be parallel. Task/Future implementations could also expose the Applicative Type ({Task, TaskAp} or something). the parallel/sequential is sort of isomorphism between monad and corresponding concurrent applicative

@safareli safareli changed the title Add spec for Chain which could support some notion of parallel composition Add spec Pearing of Monad And Applicative Oct 26, 2016
@safareli safareli changed the title Add spec Pearing of Monad And Applicative Add spec for Pearing of Monad and Applicative Oct 26, 2016
@safareli
Copy link
Member Author

safareli commented Oct 26, 2016

After reading this reddit thread i'm thinking that name Parallel or Concurent is not that precise as this spec shuold just pearing/isomorphism between some Monad and some Applicative.

This are example are not strictly related to concurrency/parallelism:

  • List Monad and ZipList Applicative
  • Either Monad and Validation Applicative

for now i don't have a better name but will think on this.

@rpominov
Copy link
Member

rpominov commented Oct 29, 2016

this spec shuold just pearing/isomorphism between some Monad and some Applicative

Not sure this worth adding to the spec. I can't imagine what kind of generic code we could write against this. I mean say we have some value of a Monadic type, and we know that we can convert it to a value of some other type that is Applicative, not sure what does this give us.

The technic itself looks good though, and can be used in Task to provide lawful parallel Applicative, but I'm not sure what we get by adding this to the spec in this particular way.

Edit: we could also still use parallel and sequential names, but this just seems too specific to particular type Task, so also doesn't feel natural to have in this spec.

@safareli
Copy link
Member Author

safareli commented Oct 29, 2016

This will be useful in Free monad like structures. for example one might have Free&FreeAp conforming to this spec user could switch from one to another when it's appropriate, and then it could be folded down to some other Monad&Applicative pear Task/Future ...

Or one might for example in one computation use Either then convert it to Validation and then back to Either (when error is monoid), but I see most use with Task/Future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants