# Bluefin, a new effect system

**URL:** <https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395>\
**Category:** Announcements\
**Created:** [April 22, 2024, 1:08pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395 "2024-04-22T13:08:04Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 22, 2024, 1:08pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/1 "2024-04-22T13:08:04Z")

</div>

I’ve mentioned my new effect system, Bluefin, a few times on this forum. It’s now ready for me to announce it more formally.

Bluefin’s API differs from all prior effect systems in that it implements a “well typed [Handle](https://jaspervdj.be/posts/2018-03-08-handle-pattern.html)/[Services](https://brandonchinn178.github.io/posts/2023/05/03/services-design-pattern) pattern”. That is, all effects are accessed through value-level handles, which makes it trivial to mix a wide variety of effects, including:

- [Bluefin.EarlyReturn](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin-EarlyReturn.html), for early return
- [Bluefin.Exception](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin-Exception.html), for exceptions
- [Bluefin.IO](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin-IO.html), for I/O
- [Bluefin.State](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin-State.html), for mutable state
- [Bluefin.Stream](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin-Stream.html), for streams

If you’re interested then read the [Introduction to Bluefin](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin.html). I’d love to know what you all think.

---

<div class="post-metadata">

**Author:** ![sgraf](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sgraf/32/392_2.png) [@sgraf](https://discourse.haskell.org/u/sgraf)\
**Post date:** [April 23, 2024, 8:53am UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/2 "2024-04-23T08:53:49Z")

</div>

From the linked Introduction:

```haskell
countPositivesNegatives :: [Int] -> String
countPositivesNegatives is = runPureEff $
  evalState (0 :: Int) $ \positives -> do
      r <- try $ \ex ->
          evalState (0 :: Int) $ \negatives -> do
              for_ is $ \i -> do
                  case compare i 0 of
                      GT -> modify positives (+ 1)
                      EQ -> throw ex ()
                      LT -> modify negatives (+ 1)

              p <- get positives
              n <- get negatives

              pure $
                "Positives: "
                  ++ show p
                  ++ ", negatives "
                  ++ show n

      case r of
          Right r' -> pure r'
          Left () -> do
              p <- get positives
              pure $
                "We saw a zero, but before that there were "
                  ++ show p
                  ++ " positives"

```

Wow, this is great work, especially seeing how seemless and idiomatically it integrates with typical Haskell code!

Have you considered combining the explicit handle- or [capability-passing style](https://se.cs.uni-tuebingen.de/publications/brachthaeuser19effekt-revision.pdf) with implicit parameters? I imagine that often there’s just a single effect of a given kind to consider. I imagine that it’s a bit like labels in Java, where you only want to give an `outer: ` label to `break` out of an outer loop.

Although arguably, when there are multiple effects involved, the naming helps. It is a shame that implicit arguments are non-standard and cumbersome to use. By contrast, the explicit naming isn’t all that annoying in the single effect case.

I imagine that GHC 15 would allow us to write `\@positives -> ... modify @positives (+ 1) ...` and leave out the implicit value argument when it can be inferred, but I’m not holding my breath yet.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 23, 2024, 9:06am UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/3 "2024-04-23T09:06:17Z")

</div>

Thanks!

> [@sgraf](#):
>
> Have you considered combining the explicit handle- or [capability-passing style](https://se.cs.uni-tuebingen.de/publications/brachthaeuser19effekt-revision.pdf) with implicit parameters?

Yes, it was suggested by @prophet, but I couldn’t get it to work. I don’t know if there’s some technical reason that it is hopeless or whether it just needs someone clever enough to work out the recipe. Someone might like to look at [my progress so far](https://github.com/tomjaguarpaw/bluefin/commit/d55a7c9dc0524fb3ffec3ff68c57547b16c698aa).

> [@sgraf](#):
>
> I imagine that GHC 15 would allow us to write `\@positives -> ... modify @positives (+ 1) ...` and leave out the implicit value argument when it can be inferred, but I’m not holding my breath yet.

Yes, I also tried that but type abstractions don’t seem good enough yet. Perhaps by GHC 15 they will be!

---

<div class="post-metadata">

**Author:** ![ocharles](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ocharles/32/102_2.png) [@ocharles](https://discourse.haskell.org/u/ocharles)\
**Post date:** [April 23, 2024, 10:29am UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/4 "2024-04-23T10:29:18Z")

</div>

This is really cool! For a long time I’ve been wondering if we could have an effect system that’s as nice to work with as `effectful` or `cleff`, but with first class effects that we pass around, rather than shuffling everything around implicitly. I was particualy motivated to explore this when I opened [“When is something an effect, and when is something a handle?”](https://github.com/haskell-effectful/effectful/discussions/137) on the `effectful` discussion board - and I still don’t know what the answer to that question is. It makes me err more on the side of preferring handles, but I’m not quite sure why. I started exploring something a bit like Bluefin myself, hoping to not need any type classes at all, but I do ultimately think you need something like your `:>` class - it basically ends up needing something like Oleg’s “Lightweight monadic regions” to scope the effect. At this point I lost interest, but kudos for pushing on - your solution is a lot cleaner than I thought would be possible!

Now the inevitable unfortunately is work has already made one massive shift to `effectful`, and probably can’t afford another anytime soon. I do wonder if there’s a way to “reify” implicit effects in effectful into an explicit handler. That would be very cool, but [your comments here](https://hackage.haskell.org/package/bluefin-0.0.4.3/docs/Bluefin.html#g:8) don’t fill me with hope

Anyway, a bit of a rambly reply - but great work! I look forward to seeing where this goes next, when it gets exercised a bit more.

(And sorry I never replied to your original email!)

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 23, 2024, 10:43am UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/5 "2024-04-23T10:43:50Z")

</div>

Thanks! I think there’s a good chance there’s an ergonomic way of converting between effectful and Bluefin, but I haven’t found it yet. One major impediment is that effectful (and all other effect libraries, I think) track effects in a type level list. Bluefin tracks them in a type level binary tree. I think the latter is much more ergonomic because it allows you to do [compound effects](https://hackage.haskell.org/package/bluefin-0.0.4.2/docs/Bluefin-Compound.html) really trivially.

---

<div class="post-metadata">

**Author:** ![ocharles](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ocharles/32/102_2.png) [@ocharles](https://discourse.haskell.org/u/ocharles)\
**Post date:** [April 23, 2024, 10:55am UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/6 "2024-04-23T10:55:25Z")

</div>

Yes, I noticed that when initially wondering why you had `:&` instead of just reusing `:` - only to realize what you’re doing. That’s quite nifty!

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 28, 2024, 3:47pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/7 "2024-04-28T15:47:09Z")

</div>

> [@ocharles](#):
>
> unfortunately is work has already made one massive shift to `effectful`, and probably can’t afford another anytime soon. I do wonder if there’s a way to “reify” implicit effects in effectful into an explicit handler.

Yes, there is. I have a work-in-progress implementation of that at [GitHub - tomjaguarpaw/bluefin-style-effectful: Bluefin-style effectful](https://github.com/tomjaguarpaw/bluefin-style-effectful). Specifically, the [`applyHandle` and `withHandle` functions](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L31-L35) convert between implicit type class style and explicit handle style. Native effectful effects are wrapped in `Handle` to become value-level handles. So, for example, you can [convert between effectful and Bluefin-style `State` operations and handlers](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L54-L67). N.B. This doesn’t allow interoperation between `effectful` and `bluefin`. Rather, it’s a value-level (Bluefin-style) API for `effectful`.

It’s going to take a bit of thinking to work out how to get the interop to be seamless, because [effectful uses `OverlappingInstaces`](https://hackage.haskell.org/package/effectful-core-2.2.1.0/docs/src/Effectful.Internal.Effect.html#line-49) to manage its type level effects whereas [Bluefin needs `IncoherentInstances`](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L23). I had to define my own `:>`.

Is this project something you’d be interested in collaborating on, by any chance?

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [April 28, 2024, 8:05pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/8 "2024-04-28T20:05:37Z")

</div>

> [@tomjaguarpaw](#):
>
> [Bluefin needs `IncoherentInstances`](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L23)

I’m pretty surprised to that. Why does it need more than just overlapping instances?

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [April 28, 2024, 9:42pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/9 "2024-04-28T21:42:28Z")

</div>

Because handlers are of the form

```haskell
handler :: (forall e. Handle e -> Eff (e :& es) r) -> ...

```

so if you have an effectful operation that uses two effects, say of type

```haskell
op :: (e1 :> effs, e2 :> effs) => Handle e1 -> Handle2 e2 -> Eff effs r

```

and you call it using `handler` like

```haskell
handle $ \h -> op h h2

```

where `h2` is bound in an outer scope, then `e1` gets instantiated to (the rigid, skolem?) `e` and `effs` gets instantiated to `e :& es`. That means we end up with the constraint `e2 :> (e :& es)`, and we need it to resolve to `e2 :> es`. That happens according to [the instance](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L21) `(e2 :> es) => e2 :> (e :& es)`. Apparently that really does need `INCOHERENT` on [the _other_ instance](https://github.com/tomjaguarpaw/bluefin-style-effectful/blob/1230794dc96e605a03d2e63dd63033c33223f818/bluefin-style-effectful-internal/src/Bluefin/Style/Effectful/Internal.hs#L23) `e :> (e :& es)` because it is a potential match for the head of the first, `e2 :> (e :& es)` (if `e ~ e2`). Now, it _can’t_ actually match, because `e` is universally quantified, but it seems that `INCOHERENT` is still needed to let GHC apply the first instance without flagging an overlap.

---

<div class="post-metadata">

**Author:** ![Leary](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/leary/32/4348_2.png) [@Leary](https://discourse.haskell.org/u/Leary)\
**Post date:** [June 5, 2024, 7:42pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/10 "2024-06-05T19:42:54Z")

</div>

> [@tomjaguarpaw](#):
>
> Now, it _can’t_ actually match, because `e` is universally quantified,

Haha. _Would that it were so._

I had almost exactly the same class in my own project, with the same instances justified by the same reasoning:

```haskell
class x <: xs where index :: Index x xs
instance {-# INCOHERENT #-} x <: (x:xs) where index = Z
instance {-# OVERLAPPABLE #-} x <: xs => x <: (y:xs) where index = S index

```

I used this class to infer from types in context which element to pull from a heterogeneous list of skolem-tagged types. The result was a frightening heisenbug that violated the guarantees of my carefully crafted types and stole days of my life.

The core issue is (in my opinion) a GHC bug, or more charitably (and I can see the argument) an unfortunate deficiency in GHC’s treatment of our unrestricted types. We use polymorphic continuations like `(forall x. ...) -> ...` to introduce new, _unique_ types into a limited scope, but from GHC’s perspective we’ve simply accepted a polymorphic argument and neglected to supply it with a concrete type.

To follow the principle of least surprise, GHC should instantiate each such case at a unique type—if it must instantiate them at all. But it does the exact opposite: they’re all defaulted to `Any`. Now instead of `e1 :> [e1, e2]` and `e2 :> [e1, e2]`, you have two dictionaries for `Any :> [Any, Any]` and a specialiser that considers them interchangeable. Disaster.

One workaround is to `NOINLINE` everything that introduces a type you want to be treated as unique—this apparently prevents the specialiser from witnessing `e1 ~ Any ~ e2`. It also obstructs optimisation and could seriously degrade performance.

Another is to manually generate and supply the unique types yourself. There’s apparently a `runExists` primitive in the wings for just this purpose ([GHC#19675](https://gitlab.haskell.org/ghc/ghc/-/issues/19675)), but it’s not implemented yet. I’ve also had a go at it myself. See [GHC#24924](https://gitlab.haskell.org/ghc/ghc/-/issues/24924) for details.

---

<div class="post-metadata">

**Author:** ![Lysxia](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lysxia/32/2916_2.png) [@Lysxia](https://discourse.haskell.org/u/Lysxia)\
**Post date:** [June 5, 2024, 8:17pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/11 "2024-06-05T20:17:29Z")

</div>

> Now instead of `e1 :> [e1, e2]` and `e2 :> [e1, e2]`, you have two dictionaries for `Any :> [Any, Any]` and a specialiser that considers them interchangeable. Disaster.

I think bluefin avoids any such issues because its `<:` class is empty, so the behavior of a program cannot be affected from getting a different dictionary than expected.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [June 5, 2024, 8:18pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/12 "2024-06-05T20:18:12Z")

</div>

That’s interesting. Thanks for sharing. In what circumstances does this arise? It would be really bad for Bluefin if the constraint `e2 :> (e :& es)` became satisfied, rather than “decaying” to `e2 :> es`!

On the other hand I don’t think it would be bad for Bluefin if the dictionary for `e1 :> (e1 :& e2)` were considered equal to the dictionary for `e2 :> (e1 :& e2)`, because both are empty in any case.

---

<div class="post-metadata">

**Author:** ![Leary](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/leary/32/4348_2.png) [@Leary](https://discourse.haskell.org/u/Leary)\
**Post date:** [June 5, 2024, 8:42pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/13 "2024-06-05T20:42:37Z")

</div>

For bluefin itself where the class has no methods, I imagine you’re fine. But in bluefin-style-effectful you take the effectful version as a superclass—that makes it vulnerable.

> [@tomjaguarpaw](#):
>
> It would be really bad for Bluefin if the constraint `e2 :> (e :& es)` became satisfied, rather than “decaying” to `e2 :> es`!

I’m not sure what you mean by this, but to my (probably flawed) understanding, the issue doesn’t affect instance resolution itself, only the dictionaries you get after the fact.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [June 5, 2024, 8:54pm UTC](https://discourse.haskell.org/t/bluefin-a-new-effect-system/9395/14 "2024-06-05T20:54:11Z")

</div>

> [@Leary](#):
>
> But in bluefin-style-effectful you take the effectful version as a superclass—that makes it vulnerable.

Ah yes, I see. And also [an experimental library](https://github.com/tomjaguarpaw/ad/blob/7ec7b273db3055c45dda17ea6ec169117dbd6367/Eff-Args/app/RoseMTL.hs#L64-L66) I wrote that puts a Bluefin-style API on top of MTL/transformers.
