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

Effects as GADTs #365

Merged
merged 35 commits into from
Mar 13, 2020
Merged

Effects as GADTs #365

merged 35 commits into from
Mar 13, 2020

Conversation

robrix
Copy link
Contributor

@robrix robrix commented Mar 12, 2020

This PR redefines all the effects as GADTs, simplifying and tidying the smart constructors and algebras considerably.

This doesn’t change its semantics at all.
This does not change its semantics.
@robrix robrix changed the base branch from master to distributive-algebra March 12, 2020 18:30
@robrix robrix mentioned this pull request Mar 13, 2020
4 tasks
@evanrelf
Copy link

Is this change mostly syntactic, or are there other implications for how effects are defined?

It looks like the GADT syntax will be a lot more straightforward and friendly compared to the old continuation style 🙂 I'm looking forward to it.

@robrix
Copy link
Contributor Author

robrix commented Mar 13, 2020

Is this change mostly syntactic, or are there other implications for how effects are defined?

Purely syntactic; it’s equivalent to the continuation style with a continuation of pure.

It looks like the GADT syntax will be a lot more straightforward and friendly compared to the old continuation style 🙂 I'm looking forward to it.

Glad to hear it! I’m quite pleased with how it’s turning out.

@robrix robrix changed the base branch from distributive-algebra to master March 13, 2020 05:33
Comment on lines -18 to +20
data Teletype m k
= Read (String -> m k)
| Write String (m k)
deriving (Functor)
data Teletype (m :: Type -> Type) k where
Read :: Teletype m String
Write :: String -> Teletype m ()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

One consequence of this change is that first-order effects in general require kind annotations for the m parameter. (This is documented in the common errors document.)

Comment on lines 31 to +32
write :: Has Teletype sig m => String -> m ()
write s = send (Write s (pure ()))
write s = send (Write s)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Having to provide continuations in smart constructors was a flaw that I am very glad to see removed.

Comment on lines +71 to +79
3. Use `Control.Effect.Labelled` to define an instance for some specific label:

```haskell
instance HasLabelled State (State s) sig m => MTL.MonadState s (Wrapper s m) where
get = Control.Effect.State.Labelled.get @State
put = Control.Effect.State.Labelled.put @State
```

Now `Wrapper` has a `MonadState` instance whenever `m` has an appropriately-labelled `State` effect, which can be provided by the `Control.Effect.Labelled.Labelled` carrier.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Figured I’d document using Labelled for mtl interop while I was in here.

@@ -2,6 +2,7 @@

This file summarizes the changelog and extracts the pieces most relevant to bringing up `fused-effects` applications to use newer versions of the library.


Copy link
Contributor Author

Choose a reason for hiding this comment

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

double 👏 space 👏 above 👏 headings

Comment on lines -143 to +146
c:cs | p c -> ParseC (put cs) *> hdl (k c <$ ctx)
c:cs | p c -> c <$ ctx <$ ParseC (put cs)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I really like the left-associativity of <$ here ✨

Comment on lines -156 to +158
alg hdl sig ctx = case sig of
L Empty -> []
R (Choose k) -> hdl (k True <$ ctx) ++ hdl (k False <$ ctx)
alg _ sig ctx = case sig of
L Empty -> []
R Choose -> [ True <$ ctx, False <$ ctx ]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is one of the best examples of how cool this change turned out to be. Lacking a continuation means we have to return a value instead of calling k with it, and that value is ctx a (whatever a is for that constructor). Since Choose :: Choose m Bool, that means we need to return [ctx Bool]. Hence, instead of concatenating the lists produced by the continuations, we produce the two-element list above and let the Monad instance for [] take care of the rest externally to alg.

All in all, this change should result in far fewer binds being issued. Many of these would ideally have been compiled away anyhow, but there’s now that much less work for the simplifier to do. And since the algebras themselves are (often dramatically!) simpler as a result, it’s win-win-win.

@@ -91,8 +92,8 @@ instance MonadTrans ChooseC where

instance Algebra sig m => Algebra (Choose :+: sig) (ChooseC m) where
alg (hdl :: forall x . ctx (n x) -> ChooseC m (ctx x)) sig (ctx :: ctx ()) = case sig of
L (Choose k) -> ChooseC $ \ fork leaf -> fork (runChoose fork leaf (hdl (k True <$ ctx))) (runChoose fork leaf (hdl (k False <$ ctx)))
R other -> ChooseC $ \ fork leaf -> thread dst hdl other (pure ctx) >>= runIdentity . runChoose (coerce fork) (coerce leaf)
L Choose -> ChooseC $ \ fork leaf -> fork (leaf (True <$ ctx)) (leaf (False <$ ctx))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the Church-encoded binary tree version of that algebra for lists above.


-- | @since 0.1.0.0
newtype Fresh m k = Fresh (Int -> m k)
deriving (Functor)
data Fresh (m :: Type -> Type) k where
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I’ve gone out of my way to use Type instead of * for the new kind signatures. I’m planning on turning the star is type warning back on at some point this release.

@robrix robrix marked this pull request as ready for review March 13, 2020 05:59
@robrix robrix merged commit 26881e2 into master Mar 13, 2020
@robrix robrix deleted the no-exit branch March 13, 2020 06:14
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

Successfully merging this pull request may close these issues.

None yet

2 participants