diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+# 0.4.2.0
+
+* Add `Bluefin.Internal.DslBuilderEff`
+
+* Add `Bluefin.Internal.Prim`
+
 # 0.4.1.0
 
 * Add `MonadFix` instance for `Eff`, thanks to Adriaan Leijnse
diff --git a/bluefin-internal.cabal b/bluefin-internal.cabal
--- a/bluefin-internal.cabal
+++ b/bluefin-internal.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin-internal
-version:            0.4.1.0
+version:            0.4.2.0
 license:            MIT
 license-file:       LICENSE
 author:             Tom Ellis
@@ -78,6 +78,7 @@
       async >= 2.2 && < 2.3,
       base >= 4.14 && < 4.23,
       unliftio-core < 0.3,
+      primitive >= 0.9,
       transformers < 0.7,
       transformers-base < 0.5,
       monad-control < 1.1
@@ -85,6 +86,7 @@
       Bluefin.Internal,
       Bluefin.Internal.CloneableHandle,
       Bluefin.Internal.DslBuilder,
+      Bluefin.Internal.DslBuilderEff,
       Bluefin.Internal.DslBuilderEffects,
       Bluefin.Internal.Examples,
       Bluefin.Internal.Exception,
@@ -92,6 +94,7 @@
       Bluefin.Internal.Key,
       Bluefin.Internal.OneWayCoercible,
       Bluefin.Internal.Pipes,
+      Bluefin.Internal.Prim,
       Bluefin.Internal.System.IO
 
 test-suite bluefin-test
diff --git a/src/Bluefin/Internal.hs b/src/Bluefin/Internal.hs
--- a/src/Bluefin/Internal.hs
+++ b/src/Bluefin/Internal.hs
@@ -1340,9 +1340,9 @@
 -- ([1,2,3,1,2,3],())
 -- @
 cycleToStream ::
-  (Foldable f, ea :> es) =>
+  (Foldable f, e1 :> es) =>
   f a ->
-  Stream a ea ->
+  Stream a e1 ->
   -- | ͘
   Eff es ()
 cycleToStream f y = do
@@ -1357,10 +1357,10 @@
 -- ([1,2,3,4],())
 -- @
 takeConsume ::
-  (ea :> es, eb :> es) =>
+  (e1 :> es, e2 :> es) =>
   Int ->
-  Consume a ea ->
-  Stream a eb ->
+  Consume a e1 ->
+  Stream a e2->
   -- | ͘
   Eff es ()
 takeConsume count source sink = loop count
diff --git a/src/Bluefin/Internal/DslBuilderEff.hs b/src/Bluefin/Internal/DslBuilderEff.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Internal/DslBuilderEff.hs
@@ -0,0 +1,57 @@
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE QuantifiedConstraints #-}
+
+module Bluefin.Internal.DslBuilderEff where
+
+import Bluefin.Internal
+import Bluefin.Internal.OneWayCoercible
+  ( OneWayCoercible,
+    oneWayCoerce,
+    oneWayCoercible,
+    oneWayCoercibleImpl,
+  )
+
+newtype DslBuilderEff h es r
+  = MkDslBuilderEff {unMkDslBuilderEff :: forall e. h e -> Eff (e :& es) r}
+
+useImplDslBuilderEff ::
+  (e :> es) =>
+  DslBuilderEff h e r ->
+  -- | ͘
+  DslBuilderEff h es r
+useImplDslBuilderEff = oneWayCoerce
+
+runDslBuilderEff ::
+  h es ->
+  DslBuilderEff h es r ->
+  -- | ͘
+  Eff es r
+runDslBuilderEff h f = makeOp (unMkDslBuilderEff f h)
+
+dslBuilderEff ::
+  (forall e. h e -> Eff (e :& es) r) ->
+  -- | ͘
+  DslBuilderEff h es r
+dslBuilderEff = MkDslBuilderEff
+
+instance
+  (e :> es) =>
+  OneWayCoercible (DslBuilderEff h e r) (DslBuilderEff h es r)
+  where
+  oneWayCoercibleImpl = oneWayCoercible
+
+instance (Handle h) => Functor (DslBuilderEff h es) where
+  fmap f g =
+    dslBuilderEff $ \h ->
+      fmap f (runDslBuilderEff (mapHandle h) (useImplDslBuilderEff g))
+
+instance (Handle h) => Applicative (DslBuilderEff h es) where
+  pure x = dslBuilderEff (pure (pure x))
+  f <*> x = dslBuilderEff $ \h ->
+    runDslBuilderEff (mapHandle h) (useImplDslBuilderEff f)
+      <*> runDslBuilderEff (mapHandle h) (useImplDslBuilderEff x)
+
+instance (Handle h) => Monad (DslBuilderEff h es) where
+  m >>= f = dslBuilderEff $ \h -> do
+    r <- runDslBuilderEff (mapHandle h) (useImplDslBuilderEff m)
+    runDslBuilderEff (mapHandle h) (useImplDslBuilderEff (f r))
diff --git a/src/Bluefin/Internal/DslBuilderEffects.hs b/src/Bluefin/Internal/DslBuilderEffects.hs
--- a/src/Bluefin/Internal/DslBuilderEffects.hs
+++ b/src/Bluefin/Internal/DslBuilderEffects.hs
@@ -1,3 +1,6 @@
+-- This will probably be superseded by DslBuilderEff because the
+-- latter has a better name
+
 {-# LANGUAGE DerivingVia #-}
 {-# LANGUAGE QuantifiedConstraints #-}
 
@@ -8,13 +11,14 @@
   ( OneWayCoercible,
     oneWayCoercible,
     oneWayCoercibleImpl,
+    oneWayCoerce,
   )
 
 newtype DslBuilderEffects h es r
   = MkDslBuilderEffects {unMkDslBuilderEffects :: forall e. h e -> Eff (e :& es) r}
 
 useImplDslBuilderEffects :: (e :> es) => DslBuilderEffects h e r -> DslBuilderEffects h es r
-useImplDslBuilderEffects (MkDslBuilderEffects f) = MkDslBuilderEffects (useImplUnder . f)
+useImplDslBuilderEffects = oneWayCoerce
 
 runDslBuilderEffects :: h es -> DslBuilderEffects h es r -> Eff es r
 runDslBuilderEffects h f = makeOp (unMkDslBuilderEffects f h)
diff --git a/src/Bluefin/Internal/Pipes.hs b/src/Bluefin/Internal/Pipes.hs
--- a/src/Bluefin/Internal/Pipes.hs
+++ b/src/Bluefin/Internal/Pipes.hs
@@ -1,6 +1,24 @@
 module Bluefin.Internal.Pipes where
 
-import Bluefin.Internal hiding (await, yield)
+import Bluefin.Internal
+  ( Coroutine,
+    Eff,
+    IOE,
+    effIO,
+    evalState,
+    forEach,
+    get,
+    mapHandle,
+    put,
+    receiveStream,
+    returnEarly,
+    useImpl,
+    useImplIn,
+    withEarlyReturn,
+    yieldCoroutine,
+    (:&),
+    (:>),
+  )
 import Bluefin.Internal qualified
 import Control.Monad (forever)
 import Data.Foldable (for_)
diff --git a/src/Bluefin/Internal/Prim.hs b/src/Bluefin/Internal/Prim.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/Internal/Prim.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE DerivingVia #-}
+
+module Bluefin.Internal.Prim where
+
+import Bluefin.Internal
+import Bluefin.Internal.OneWayCoercible
+import Control.Monad.Primitive qualified as P
+import GHC.Exts (State#)
+import Unsafe.Coerce (unsafeCoerce)
+
+-- I suppose morally this is
+--
+--   (State# (PrimStateEff e -> (# State# (PrimStateEff e), a #))
+--
+-- but since there can only be one valid implementation it doesn't
+-- seem worth doing it like that.
+data Prim (e :: Effects) = UnsafeMkPrim
+  deriving Handle via OneWayCoercibleHandle Prim
+
+data PrimStateEff es
+
+instance (e :> es) => OneWayCoercible (Prim e) (Prim es) where
+  oneWayCoercibleImpl = unsafeOneWayCoercible
+
+primitive ::
+  (e1 :> es, e2 :> es) =>
+  Prim e1 ->
+  (State# (PrimStateEff e2) -> (# State# (PrimStateEff e2), a #)) ->
+  -- | ͘
+  Eff es a
+primitive UnsafeMkPrim = unsafeCoerce (P.primitive @IO)
