packages feed

bluefin-internal 0.2.1.0 → 0.3.0.0

raw patch · 5 files changed

+267/−85 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Bluefin.Internal: instance Bluefin.Internal.Handle (Bluefin.Internal.Exception s)
+ Bluefin.Internal: MkOneWayCoercibleHandle :: a es -> OneWayCoercibleHandle (a :: k -> Type) (es :: k)
+ Bluefin.Internal: handleOneWayCoercible :: forall (h :: Effects -> Type). (forall (e :: Effects) (es :: Effects). e :> es => OneWayCoercible (h e) (h es)) => HandleD h
+ Bluefin.Internal: handleOneWayCoercion :: (forall (e :: Effects) (es :: Effects). e :> es => OneWayCoercion (h e) (h es)) -> HandleD h
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.ConstEffect r e) (Bluefin.Internal.ConstEffect r es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Coroutine a b e) (Bluefin.Internal.Coroutine a b es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Eff e r) (Bluefin.Internal.Eff es r)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Eff e) (Bluefin.Internal.Eff es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Exception ex e) (Bluefin.Internal.Exception ex es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.IOE e) (Bluefin.Internal.IOE es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Reader r e) (Bluefin.Internal.Reader r es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.State s e) (Bluefin.Internal.State s es)
+ Bluefin.Internal: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Writer w e) (Bluefin.Internal.Writer w es)
+ Bluefin.Internal: instance (forall (e' :: Bluefin.Internal.Effects) (es' :: Bluefin.Internal.Effects). (e' Bluefin.Internal.:> es') => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.OneWayCoercibleHandle h e') (Bluefin.Internal.OneWayCoercibleHandle h es')) => Bluefin.Internal.Handle (Bluefin.Internal.OneWayCoercibleHandle h)
+ Bluefin.Internal: instance Bluefin.Internal.Handle (Bluefin.Internal.Exception exn)
+ Bluefin.Internal: instance forall k (a :: k -> *) (es :: k). GHC.Generics.Generic (Bluefin.Internal.OneWayCoercibleHandle a es)
+ Bluefin.Internal: instance forall k (h :: k -> *) (e :: k) (es :: k). Bluefin.Internal.OneWayCoercible.OneWayCoercible (h e) (h es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.OneWayCoercibleHandle h e) (Bluefin.Internal.OneWayCoercibleHandle h es)
+ Bluefin.Internal: newtype OneWayCoercibleHandle (a :: k -> Type) (es :: k)
+ Bluefin.Internal.Examples: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Examples.Application e) (Bluefin.Internal.Examples.Application es)
+ Bluefin.Internal.Examples: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Examples.Counter5 e) (Bluefin.Internal.Examples.Counter5 es)
+ Bluefin.Internal.Examples: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Examples.Counter6 e) (Bluefin.Internal.Examples.Counter6 es)
+ Bluefin.Internal.Examples: instance (e Bluefin.Internal.:> es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.Examples.FileSystem e) (Bluefin.Internal.Examples.FileSystem es)
+ Bluefin.Internal.Examples: instance GHC.Generics.Generic (Bluefin.Internal.Examples.Application e)
+ Bluefin.Internal.Examples: instance GHC.Generics.Generic (Bluefin.Internal.Examples.Counter5 e)
+ Bluefin.Internal.Examples: instance GHC.Generics.Generic (Bluefin.Internal.Examples.Counter6 e)
+ Bluefin.Internal.Examples: instance GHC.Generics.Generic (Bluefin.Internal.Examples.FileSystem es)
+ Bluefin.Internal.OneWayCoercible: MkOneWayCoercibleD :: OneWayCoercion a b -> OneWayCoercibleD (a :: k) (b :: k)
+ Bluefin.Internal.OneWayCoercible: MkOneWayCoercion :: Coercion a b -> OneWayCoercion (a :: k) (b :: k)
+ Bluefin.Internal.OneWayCoercible: class GOneWayCoercible (a :: k) (b :: k1)
+ Bluefin.Internal.OneWayCoercible: class Generic a
+ Bluefin.Internal.OneWayCoercible: class OneWayCoercible (a :: k) (b :: k)
+ Bluefin.Internal.OneWayCoercible: gOneWayCoercible :: forall {k} h (e :: k) (es :: k). GOneWayCoercible (Rep (h e)) (Rep (h es)) => OneWayCoercibleD (h e) (h es)
+ Bluefin.Internal.OneWayCoercible: gOneWayCoercible2 :: forall {k1} {k2} h (e :: k1) (e' :: k2) (es :: k1) (es' :: k2). GOneWayCoercible (Rep (h e e')) (Rep (h es es')) => OneWayCoercibleD (h e e') (h es es')
+ Bluefin.Internal.OneWayCoercible: gOneWayCoercion :: GOneWayCoercible (Rep a) (Rep b) => OneWayCoercion a b
+ Bluefin.Internal.OneWayCoercible: instance (Bluefin.Internal.OneWayCoercible.OneWayCoercible a a', Bluefin.Internal.OneWayCoercible.OneWayCoercible b b') => Bluefin.Internal.OneWayCoercible.OneWayCoercible (a' -> b) (a -> b')
+ Bluefin.Internal.OneWayCoercible: instance (Bluefin.Internal.OneWayCoercible.OneWayCoercible a1 a2, Bluefin.Internal.OneWayCoercible.OneWayCoercible b1 b2) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Data.Either.Either a1 b1) (Data.Either.Either a2 b2)
+ Bluefin.Internal.OneWayCoercible: instance (Bluefin.Internal.OneWayCoercible.OneWayCoercible a1 a2, Bluefin.Internal.OneWayCoercible.OneWayCoercible b1 b2) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (a1, b1) (a2, b2)
+ Bluefin.Internal.OneWayCoercible: instance Bluefin.Internal.OneWayCoercible.GOneWayCoercible GHC.Generics.U1 GHC.Generics.U1
+ Bluefin.Internal.OneWayCoercible: instance Bluefin.Internal.OneWayCoercible.OneWayCoercible () ()
+ Bluefin.Internal.OneWayCoercible: instance Bluefin.Internal.OneWayCoercible.OneWayCoercible a1 a2 => Bluefin.Internal.OneWayCoercible.OneWayCoercible (GHC.Maybe.Maybe a1) (GHC.Maybe.Maybe a2)
+ Bluefin.Internal.OneWayCoercible: instance Bluefin.Internal.OneWayCoercible.OneWayCoercible c c' => Bluefin.Internal.OneWayCoercible.GOneWayCoercible (GHC.Generics.K1 i c) (GHC.Generics.K1 i' c')
+ Bluefin.Internal.OneWayCoercible: instance forall k (s :: k). Bluefin.Internal.OneWayCoercible.OneWayCoercible s s
+ Bluefin.Internal.OneWayCoercible: instance forall k1 k2 (f :: k1 -> *) (f' :: k2 -> *) (g :: k1 -> *) (g' :: k2 -> *). (Bluefin.Internal.OneWayCoercible.GOneWayCoercible f f', Bluefin.Internal.OneWayCoercible.GOneWayCoercible g g') => Bluefin.Internal.OneWayCoercible.GOneWayCoercible (f GHC.Generics.:*: g) (f' GHC.Generics.:*: g')
+ Bluefin.Internal.OneWayCoercible: instance forall k1 k2 (f :: k1 -> *) (f' :: k2 -> *) i (t :: GHC.Generics.Meta) i' (t' :: GHC.Generics.Meta). Bluefin.Internal.OneWayCoercible.GOneWayCoercible f f' => Bluefin.Internal.OneWayCoercible.GOneWayCoercible (GHC.Generics.M1 i t f) (GHC.Generics.M1 i' t' f')
+ Bluefin.Internal.OneWayCoercible: newtype OneWayCoercibleD (a :: k) (b :: k)
+ Bluefin.Internal.OneWayCoercible: newtype OneWayCoercion (a :: k) (b :: k)
+ Bluefin.Internal.OneWayCoercible: oneWayCoerce :: OneWayCoercible a b => a -> b
+ Bluefin.Internal.OneWayCoercible: oneWayCoerceWith :: OneWayCoercion a b -> a -> b
+ Bluefin.Internal.OneWayCoercible: oneWayCoercible :: forall {k} (a :: k) (b :: k). Coercible a b => OneWayCoercibleD a b
+ Bluefin.Internal.OneWayCoercible: oneWayCoercibleImpl :: OneWayCoercible a b => OneWayCoercibleD a b
+ Bluefin.Internal.OneWayCoercible: oneWayCoercion :: forall {k} (a :: k) (b :: k). OneWayCoercible a b => OneWayCoercion a b
+ Bluefin.Internal.OneWayCoercible: trans :: forall {k} (a :: k) (b :: k) (c :: k). OneWayCoercion a b -> OneWayCoercion b c -> OneWayCoercion a c
+ Bluefin.Internal.OneWayCoercible: unsafeCoercionOfOneWayCoercible :: forall {k} (a :: k) (b :: k). OneWayCoercible a b => Coercion a b
+ Bluefin.Internal.OneWayCoercible: unsafeCoercionOfOneWayCoercion :: forall {k} (a :: k) (b :: k). OneWayCoercion a b -> Coercion a b
+ Bluefin.Internal.OneWayCoercible: unsafeOneWayCoercible :: forall {k} (a :: k) (b :: k). OneWayCoercibleD a b
+ Bluefin.Internal.OneWayCoercible: unsafeOneWayCoercion :: forall {k} (a :: k) (b :: k). OneWayCoercion a b
- Bluefin.Internal.Examples: DynamicReader :: (forall (e' :: Effects). () => Eff (e' :& e) r) -> (forall (e' :: Effects) a. () => (r -> r) -> Eff e' a -> Eff (e' :& e) a) -> DynamicReader r (e :: Effects)
+ Bluefin.Internal.Examples: DynamicReader :: Eff e r -> (forall (e' :: Effects) a. () => (r -> r) -> Eff e' a -> Eff (e' :& e) a) -> DynamicReader r (e :: Effects)
- Bluefin.Internal.Examples: MkApplication :: (forall (e' :: Effects). () => String -> Int -> Eff (e' :& e) [String]) -> State (Int, Bool) e -> Stream String e -> Application (e :: Effects)
+ Bluefin.Internal.Examples: MkApplication :: (String -> Int -> Eff e [String]) -> State (Int, Bool) e -> Stream String e -> Application (e :: Effects)
- Bluefin.Internal.Examples: MkCounter5 :: (forall (e' :: Effects). () => Eff (e' :& e) ()) -> (forall (e' :: Effects). () => String -> Eff (e' :& e) Int) -> Counter5 (e :: Effects)
+ Bluefin.Internal.Examples: MkCounter5 :: Eff e () -> (String -> Eff e Int) -> Counter5 (e :: Effects)
- Bluefin.Internal.Examples: MkCounter6 :: (forall (e' :: Effects). () => Eff (e' :& e) ()) -> State Int e -> Stream String e -> Counter6 (e :: Effects)
+ Bluefin.Internal.Examples: MkCounter6 :: Eff e () -> State Int e -> Stream String e -> Counter6 (e :: Effects)
- Bluefin.Internal.Examples: MkFileSystem :: (forall (e :: Effects). () => FilePath -> Eff (e :& es) String) -> (forall (e :: Effects). () => FilePath -> String -> Eff (e :& es) ()) -> FileSystem (es :: Effects)
+ Bluefin.Internal.Examples: MkFileSystem :: (FilePath -> Eff es String) -> (FilePath -> String -> Eff es ()) -> FileSystem (es :: Effects)
- Bluefin.Internal.Examples: [askLRImpl] :: DynamicReader r (e :: Effects) -> forall (e' :: Effects). () => Eff (e' :& e) r
+ Bluefin.Internal.Examples: [askLRImpl] :: DynamicReader r (e :: Effects) -> Eff e r
- Bluefin.Internal.Examples: [getCounter5Impl] :: Counter5 (e :: Effects) -> forall (e' :: Effects). () => String -> Eff (e' :& e) Int
+ Bluefin.Internal.Examples: [getCounter5Impl] :: Counter5 (e :: Effects) -> String -> Eff e Int
- Bluefin.Internal.Examples: [incCounter5Impl] :: Counter5 (e :: Effects) -> forall (e' :: Effects). () => Eff (e' :& e) ()
+ Bluefin.Internal.Examples: [incCounter5Impl] :: Counter5 (e :: Effects) -> Eff e ()
- Bluefin.Internal.Examples: [incCounter6Impl] :: Counter6 (e :: Effects) -> forall (e' :: Effects). () => Eff (e' :& e) ()
+ Bluefin.Internal.Examples: [incCounter6Impl] :: Counter6 (e :: Effects) -> Eff e ()
- Bluefin.Internal.Examples: [queryDatabase] :: Application (e :: Effects) -> forall (e' :: Effects). () => String -> Int -> Eff (e' :& e) [String]
+ Bluefin.Internal.Examples: [queryDatabase] :: Application (e :: Effects) -> String -> Int -> Eff e [String]
- Bluefin.Internal.Examples: [readFileImpl] :: FileSystem (es :: Effects) -> forall (e :: Effects). () => FilePath -> Eff (e :& es) String
+ Bluefin.Internal.Examples: [readFileImpl] :: FileSystem (es :: Effects) -> FilePath -> Eff es String
- Bluefin.Internal.Examples: [writeFileImpl] :: FileSystem (es :: Effects) -> forall (e :: Effects). () => FilePath -> String -> Eff (e :& es) ()
+ Bluefin.Internal.Examples: [writeFileImpl] :: FileSystem (es :: Effects) -> FilePath -> String -> Eff es ()

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+# 0.3.0.0++* Add `Bluefin.Internal.OneWayCoercible` module and related instances++* Add `Bluefin.Internal.OneWayCoercibleHandle` and related functions+ ## 0.2.1.0  * Add `handleImpl`, `HandleD` and `handleMapHandle`
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               bluefin-internal-version:            0.2.1.0+version:            0.3.0.0 license:            MIT license-file:       LICENSE author:             Tom Ellis@@ -86,6 +86,7 @@       Bluefin.Internal.Examples,       Bluefin.Internal.Exception.Scoped,       Bluefin.Internal.Key,+      Bluefin.Internal.OneWayCoercible,       Bluefin.Internal.Pipes,       Bluefin.Internal.System.IO 
src/Bluefin/Internal.hs view
@@ -2,15 +2,26 @@ {-# LANGUAGE DerivingVia #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuantifiedConstraints #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UnliftedNewtypes #-} {-# OPTIONS_HADDOCK not-home #-}  module Bluefin.Internal where  import qualified Bluefin.Internal.Exception.Scoped as ScopedException+import Bluefin.Internal.OneWayCoercible+  ( OneWayCoercible (oneWayCoercibleImpl),+    OneWayCoercion,+    gOneWayCoercible,+    oneWayCoerce,+    oneWayCoerceWith,+    oneWayCoercible,+    unsafeOneWayCoercible,+  ) import qualified Control.Concurrent.Async as Async import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar) import qualified Control.Exception@@ -27,6 +38,7 @@ import Data.Proxy (Proxy (Proxy)) import Data.Type.Coercion (Coercion (Coercion)) import GHC.Exts (Proxy#, proxy#)+import GHC.Generics (Generic) import System.IO.Unsafe (unsafePerformIO) import Unsafe.Coerce (unsafeCoerce) import Prelude hiding (drop, head, read, return)@@ -40,12 +52,18 @@  type (:&) = Union -type role Eff nominal representational- newtype Eff (es :: Effects) a = UnsafeMkEff {unsafeUnEff :: IO a}   deriving stock (Functor)   deriving newtype (Applicative, Monad) +type role Eff nominal representational++instance (e :> es) => OneWayCoercible (Eff e) (Eff es) where+  oneWayCoercibleImpl = oneWayCoercible++instance (e :> es) => OneWayCoercible (Eff e r) (Eff es r) where+  oneWayCoercibleImpl = oneWayCoercible+ -- | Because doing 'IO' operations inside 'Eff' requires a value-level -- argument we can't give @IO@-related instances to @Eff@ directly. -- Instead we wrap it in @EffReader@.@@ -327,18 +345,30 @@ -- | Handle to an exception of type @exn@ newtype Exception exn (e :: Effects)   = MkException (forall a. exn -> Eff e a)+  deriving (Handle) via OneWayCoercibleHandle (Exception exn)  type role Exception representational nominal +instance (e :> es) => OneWayCoercible (Exception ex e) (Exception ex es) where+  oneWayCoercibleImpl = oneWayCoercible+ -- | A handle to a strict mutable state of type @s@ newtype State s (e :: Effects) = UnsafeMkState (IORef s)+  deriving (Handle) via OneWayCoercibleHandle (State s)  type role State representational nominal +instance (e :> es) => OneWayCoercible (State s e) (State s es) where+  oneWayCoercibleImpl = oneWayCoercible+ -- | A handle to a coroutine that yields values of type @a@ and then -- expects values of type @b@. newtype Coroutine a b (e :: Effects) = MkCoroutine (a -> Eff e b)+  deriving (Handle) via OneWayCoercibleHandle (Coroutine a b) +instance (e :> es) => OneWayCoercible (Coroutine a b e) (Coroutine a b es) where+  oneWayCoercibleImpl = oneWayCoercible+ -- | A handle to a stream that yields values of type @a@.  It is -- implemented as a handle to a coroutine that yields values of type -- @a@ and then expects values of type @()@.@@ -358,30 +388,15 @@ -- -- @ -- data Application e = MkApplication---   { queryDatabase :: forall e'. String -> Int -> Eff (e' :& e) [String],+--   { queryDatabase :: String -> Int -> Eff e [String], --     applicationState :: State (Int, Bool) e, --     logger :: Stream String e --   }--- @------ To define @mapHandle@ for @Application@ you should apply--- @mapHandle@ to all the fields that are themeselves handles and--- apply 'useImplUnder' to all the fields that are dynamic effects:+--   deriving (Generic)+--   deriving (Handle) via 'OneWayCoercibleHandle' Application ----- @--- instance Handle Application where---   'handleImpl' =---     'handleMapHandle' $---       \\MkApplication---          { queryDatabase = q,---            applicationState = a,---            logger = l---          } ->---           MkApplication---             { queryDatabase = \\s i -> 'useImplUnder' (q s i),---               applicationState = 'mapHandle' a,---               logger = mapHandle l---             }+-- instance (e :> es) => 'OneWayCoercible' (Application e) (Application es) where+--   oneWayCoercibleImpl = 'gOneWayCoercible' -- @ class Handle (h :: Effects -> Type) where   {-# MINIMAL handleImpl | mapHandle #-}@@ -405,6 +420,22 @@   -- you should change it to   --   -- @+  -- data MyHandle e = ...+  --   deriving (Generic)+  --   deriving (Handle) via OneWayCoercibleHandle MyHandle+  --+  -- instance (e :> es) => OneWayCoercible (MyHandle e) (MyHandle es) where+  --   oneWayCoercibleImpl = gOneWayCoercible+  -- @+  --+  -- If that doesn't work for any reason you can always reuse your old+  -- definition of @mapHandle@ as follows.  However,+  -- 'handleMapHandle' will be removed at some point in the future, so+  -- you can [open a new issue on+  -- Bluefin](https://github.com/tomjaguarpaw/bluefin/issues/new) to+  -- ask for advice.+  --+  -- @   -- instance Handle MyHandle where   --   handleImpl = handleMapHandle $ \\h -> \<definition\>   -- @@@ -422,23 +453,40 @@   HandleD h handleMapHandle = MkHandleD -instance Handle (State s) where-  handleImpl = handleMapHandle $ \(UnsafeMkState s) -> UnsafeMkState s+handleOneWayCoercible ::+  (forall e es. (e :> es) => OneWayCoercible (h e) (h es)) =>+  -- | ͘+  HandleD h+handleOneWayCoercible = MkHandleD oneWayCoerce -instance Handle (Exception s) where-  handleImpl = handleMapHandle $ \(MkException s) ->-    MkException (weakenEff has . s)+handleOneWayCoercion ::+  (forall e es. (e :> es) => OneWayCoercion (h e) (h es)) ->+  -- | ͘+  HandleD h+handleOneWayCoercion owc = MkHandleD (oneWayCoerceWith owc) -instance Handle (Coroutine a b) where-  handleImpl = handleMapHandle $ \(MkCoroutine f) ->-    MkCoroutine (fmap useImpl f)+-- { OneWayCoercibleHandle -instance Handle (Writer w) where-  handleImpl = handleMapHandle $ \(Writer wr) -> Writer (mapHandle wr)+-- | 'OneWayCoercibleHandle' is used to derive 'Handle' instances+-- using @DerivingVia@+newtype OneWayCoercibleHandle a es = MkOneWayCoercibleHandle (a es)+  deriving stock (Generic) -instance Handle IOE where-  handleImpl = handleMapHandle $ \MkIOE -> MkIOE+instance+  forall h.+  (forall e' es'. (e' :> es') => OneWayCoercible (OneWayCoercibleHandle h e') (OneWayCoercibleHandle h es')) =>+  Handle (OneWayCoercibleHandle h)+  where+  handleImpl = handleOneWayCoercible +instance+  (OneWayCoercible (h e) (h es)) =>+  OneWayCoercible (OneWayCoercibleHandle h e) (OneWayCoercibleHandle h es)+  where+  oneWayCoercibleImpl = gOneWayCoercible++-- }+ -- | A convenience type whose only purpose is to avoid writing @(# #)@ -- as an argument to functions which are only function because -- top-level definitions of unlifted kind are forbidden.@@ -1286,9 +1334,13 @@  -- | Handle that allows you to run 'IO' operations data IOE (e :: Effects) = MkIOE+  deriving (Handle) via OneWayCoercibleHandle IOE  type role IOE nominal +instance (e :> es) => OneWayCoercible (IOE e) (IOE es) where+  oneWayCoercibleImpl = unsafeOneWayCoercible+ -- | Run an 'IO' operation in 'Eff' -- -- @@@ -1373,7 +1425,11 @@     Left (l, _) -> Left l  newtype Writer w e = Writer (Stream w e)+  deriving (Handle) via OneWayCoercibleHandle (Writer w) +instance (e :> es) => OneWayCoercible (Writer w e) (Writer w es) where+  oneWayCoercibleImpl = oneWayCoercible+ -- | -- @ -- >>> 'Data.Monoid.getAny' $ snd $ runPureEff $ runWriter $ \\w -> do@@ -1429,6 +1485,9 @@ newtype Reader r e = MkReader (State r e)   deriving newtype (Handle) +instance (e :> es) => OneWayCoercible (Reader r e) (Reader r es) where+  oneWayCoercibleImpl = oneWayCoercible+ runReader ::   -- | Initial value for @Reader@.   r ->@@ -1548,16 +1607,20 @@     useImplIn k h'  instance (Handle h) => Handle (HandleReader h) where+  -- This handleImpl is now a special case that doesn't use+  -- OneWayCoercion. We can only fix that when we store a+  -- OneWayCoercion inside `Handle`.   handleImpl = handleMapHandle mapHandleReader  newtype ConstEffect r (e :: Effects) = MkConstEffect r+  deriving (Handle) via OneWayCoercibleHandle (ConstEffect r) +instance (e :> es) => OneWayCoercible (ConstEffect r e) (ConstEffect r es) where+  oneWayCoercibleImpl = oneWayCoercible+ runConstEffect ::   r ->   (forall e. ConstEffect r e -> Eff (e :& es) a) ->   -- | ͘   Eff es a runConstEffect r k = useImplIn k (MkConstEffect r)--instance Handle (ConstEffect r) where-  handleImpl = handleMapHandle coerce
src/Bluefin/Internal/Examples.hs view
@@ -1,9 +1,14 @@+{-# LANGUAGE DerivingVia #-} {-# LANGUAGE NoMonoLocalBinds #-} {-# LANGUAGE NoMonomorphismRestriction #-}  module Bluefin.Internal.Examples where  import Bluefin.Internal hiding (b, w)+import Bluefin.Internal.OneWayCoercible+  ( OneWayCoercible (oneWayCoercibleImpl),+    gOneWayCoercible,+  ) import Bluefin.Internal.Pipes   ( Producer,     runEffect,@@ -20,6 +25,7 @@ import Data.Foldable (for_) import Data.Monoid (Any (Any, getAny)) import Data.Proxy (Proxy (Proxy))+import GHC.Generics (Generic) import Text.Read (readMaybe) import Prelude hiding   ( break,@@ -663,22 +669,20 @@ -- Counter 5  data Counter5 e = MkCounter5-  { incCounter5Impl :: forall e'. Eff (e' :& e) (),-    getCounter5Impl :: forall e'. String -> Eff (e' :& e) Int+  { incCounter5Impl :: Eff e (),+    getCounter5Impl :: String -> Eff e Int   }+  deriving (Generic)+  deriving (Handle) via OneWayCoercibleHandle Counter5 -instance Handle Counter5 where-  handleImpl = handleMapHandle $ \c ->-    MkCounter5-      { incCounter5Impl = useImplUnder (incCounter5Impl c),-        getCounter5Impl = \msg -> useImplUnder (getCounter5Impl c msg)-      }+instance (e :> es) => OneWayCoercible (Counter5 e) (Counter5 es) where+  oneWayCoercibleImpl = gOneWayCoercible  incCounter5 :: (e :> es) => Counter5 e -> Eff es ()-incCounter5 e = makeOp (incCounter5Impl (mapHandle e))+incCounter5 e = incCounter5Impl (mapHandle e)  getCounter5 :: (e :> es) => Counter5 e -> String -> Eff es Int-getCounter5 e msg = makeOp (getCounter5Impl (mapHandle e) msg)+getCounter5 e msg = getCounter5Impl (mapHandle e) msg  runCounter5 ::   (e1 :> es) =>@@ -723,21 +727,18 @@ -- Counter 6  data Counter6 e = MkCounter6-  { incCounter6Impl :: forall e'. Eff (e' :& e) (),+  { incCounter6Impl :: Eff e (),     counter6State :: State Int e,     counter6Stream :: Stream String e   }+  deriving (Generic)+  deriving (Handle) via OneWayCoercibleHandle Counter6 -instance Handle Counter6 where-  handleImpl = handleMapHandle $ \c ->-    MkCounter6-      { incCounter6Impl = useImplUnder (incCounter6Impl c),-        counter6State = mapHandle (counter6State c),-        counter6Stream = mapHandle (counter6Stream c)-      }+instance (e :> es) => OneWayCoercible (Counter6 e) (Counter6 es) where+  oneWayCoercibleImpl = gOneWayCoercible  incCounter6 :: (e :> es) => Counter6 e -> Eff es ()-incCounter6 e = makeOp (incCounter6Impl (mapHandle e))+incCounter6 e = incCounter6Impl (mapHandle e)  getCounter6 :: (e :> es) => Counter6 e -> String -> Eff es Int getCounter6 (MkCounter6 _ st y) msg = do@@ -860,23 +861,21 @@ -- FileSystem  data FileSystem es = MkFileSystem-  { readFileImpl :: forall e. FilePath -> Eff (e :& es) String,-    writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) ()+  { readFileImpl :: FilePath -> Eff es String,+    writeFileImpl :: FilePath -> String -> Eff es ()   }+  deriving (Generic)+  deriving (Handle) via OneWayCoercibleHandle FileSystem -instance Handle FileSystem where-  handleImpl = handleMapHandle $ \fs ->-    MkFileSystem-      { readFileImpl = \fp -> useImplUnder (readFileImpl fs fp),-        writeFileImpl = \fp s -> useImplUnder (writeFileImpl fs fp s)-      }+instance (e :> es) => OneWayCoercible (FileSystem e) (FileSystem es) where+  oneWayCoercibleImpl = gOneWayCoercible  readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String-readFile fs filepath = makeOp (readFileImpl (mapHandle fs) filepath)+readFile fs filepath = readFileImpl (mapHandle fs) filepath  writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es () writeFile fs filepath contents =-  makeOp (writeFileImpl (mapHandle fs) filepath contents)+  writeFileImpl (mapHandle fs) filepath contents  runFileSystemPure ::   (e1 :> es) =>@@ -948,24 +947,15 @@ -- instance Handle example  data Application e = MkApplication-  { queryDatabase :: forall e'. String -> Int -> Eff (e' :& e) [String],+  { queryDatabase :: String -> Int -> Eff e [String],     applicationState :: State (Int, Bool) e,     logger :: Stream String e   }+  deriving (Generic)+  deriving (Handle) via OneWayCoercibleHandle Application -instance Handle Application where-  handleImpl =-    handleMapHandle $-      \MkApplication-         { queryDatabase = q,-           applicationState = a,-           logger = l-         } ->-          MkApplication-            { queryDatabase = \s i -> useImplUnder (q s i),-              applicationState = mapHandle a,-              logger = mapHandle l-            }+instance (e :> es) => OneWayCoercible (Application e) (Application es) where+  oneWayCoercibleImpl = gOneWayCoercible  -- This example shows a case where we can use @bracket@ polymorphically -- in order to perform correct cleanup if @es@ is instantiated to a@@ -1047,14 +1037,14 @@     Right contents -> contents  data DynamicReader r e = DynamicReader-  { askLRImpl :: forall e'. Eff (e' :& e) r,+  { askLRImpl :: Eff e r,     localLRImpl :: forall e' a. (r -> r) -> Eff e' a -> Eff (e' :& e) a   }  instance Handle (DynamicReader r) where   handleImpl = handleMapHandle $ \h ->     DynamicReader-      { askLRImpl = useImplUnder (askLRImpl h),+      { askLRImpl = useImpl (askLRImpl h),         localLRImpl = \f k -> useImplUnder (localLRImpl h f k)       } @@ -1062,7 +1052,7 @@   (e :> es) =>   DynamicReader r e ->   Eff es r-askLR c = makeOp (askLRImpl (mapHandle c))+askLR c = askLRImpl (mapHandle c)  localLR ::   (e :> es) =>@@ -1082,7 +1072,7 @@       k       DynamicReader         { askLRImpl = ask h,-          localLRImpl = \f k' -> makeOp (local h f (useImpl k'))+          localLRImpl = \f k' -> local h f (useImpl k')         }  -- Fails to compile unless '(e :> es) => e :> (x :& es)' is incoherent
+ src/Bluefin/Internal/OneWayCoercible.hs view
@@ -0,0 +1,122 @@+{-# OPTIONS_HADDOCK not-home #-}++module Bluefin.Internal.OneWayCoercible+  ( module Bluefin.Internal.OneWayCoercible,+    Generic,+  )+where++import Data.Coerce (Coercible, coerce)+import Data.Type.Coercion (Coercion (Coercion))+import GHC.Generics+import Unsafe.Coerce (unsafeCoerce)++gOneWayCoercion ::+  forall a b. (GOneWayCoercible (Rep a) (Rep b)) => OneWayCoercion a b+gOneWayCoercion = unsafeOneWayCoercion++gOneWayCoercible ::+  (GOneWayCoercible (Rep (h e)) (Rep (h es))) =>+  -- | ͘+  OneWayCoercibleD (h e) (h es)+gOneWayCoercible = MkOneWayCoercibleD gOneWayCoercion++gOneWayCoercible2 ::+  (GOneWayCoercible (Rep (h e e')) (Rep (h es es'))) =>+  OneWayCoercibleD (h e e') (h es es')+gOneWayCoercible2 = MkOneWayCoercibleD gOneWayCoercion++oneWayCoercible :: (Coercible a b) => OneWayCoercibleD a b+oneWayCoercible = MkOneWayCoercibleD (MkOneWayCoercion Coercion)++unsafeOneWayCoercion :: forall a b. OneWayCoercion a b+unsafeOneWayCoercion = MkOneWayCoercion (unsafeCoerce (Coercion @a @a))++unsafeOneWayCoercible :: forall a b. OneWayCoercibleD a b+unsafeOneWayCoercible = MkOneWayCoercibleD unsafeOneWayCoercion++newtype OneWayCoercion a b = MkOneWayCoercion (Coercion a b)++newtype OneWayCoercibleD a b = MkOneWayCoercibleD (OneWayCoercion a b)++oneWayCoercion :: (OneWayCoercible a b) => OneWayCoercion a b+oneWayCoercion = case oneWayCoercibleImpl of+  MkOneWayCoercibleD oneWay -> oneWay++oneWayCoerce :: forall a b. (OneWayCoercible a b) => a -> b+oneWayCoerce = oneWayCoerceWith (oneWayCoercion @a @b)++oneWayCoerceWith :: OneWayCoercion a b -> a -> b+oneWayCoerceWith (MkOneWayCoercion Coercion) = coerce++unsafeCoercionOfOneWayCoercion :: OneWayCoercion a b -> Coercion a b+unsafeCoercionOfOneWayCoercion (MkOneWayCoercion c) = c++unsafeCoercionOfOneWayCoercible ::+  forall a b. (OneWayCoercible a b) => Coercion a b+unsafeCoercionOfOneWayCoercible = case oneWayCoercion @a @b of+  MkOneWayCoercion c -> c++class OneWayCoercible a b where+  oneWayCoercibleImpl :: OneWayCoercibleD a b++instance {-# INCOHERENT #-} OneWayCoercible s s where+  oneWayCoercibleImpl = oneWayCoercible++instance OneWayCoercible () () where+  oneWayCoercibleImpl = oneWayCoercible++instance+  (OneWayCoercible a1 a2) =>+  OneWayCoercible (Maybe a1) (Maybe a2)+  where+  oneWayCoercibleImpl = case unsafeCoercionOfOneWayCoercible @a1 @a2 of+    Coercion -> oneWayCoercible++instance+  (OneWayCoercible a1 a2, OneWayCoercible b1 b2) =>+  OneWayCoercible (Either a1 b1) (Either a2 b2)+  where+  oneWayCoercibleImpl = case unsafeCoercionOfOneWayCoercible @a1 @a2 of+    Coercion -> case unsafeCoercionOfOneWayCoercible @b1 @b2 of+      Coercion -> oneWayCoercible++-- | Other sizes of tuples follow this pattern. We will add them when+-- someone needs them.+instance+  (OneWayCoercible a1 a2, OneWayCoercible b1 b2) =>+  OneWayCoercible (a1, b1) (a2, b2)+  where+  oneWayCoercibleImpl = case unsafeCoercionOfOneWayCoercible @a1 @a2 of+    Coercion -> case unsafeCoercionOfOneWayCoercible @b1 @b2 of+      Coercion -> oneWayCoercible++trans :: OneWayCoercion a b -> OneWayCoercion b c -> OneWayCoercion a c+trans c1 c2 = case unsafeCoercionOfOneWayCoercion c1 of+  Coercion -> case unsafeCoercionOfOneWayCoercion c2 of+    Coercion -> MkOneWayCoercion Coercion++class GOneWayCoercible a b++instance GOneWayCoercible U1 U1++instance+  (OneWayCoercible c c') =>+  GOneWayCoercible (K1 i c) (K1 i' c')++instance+  (GOneWayCoercible f f') =>+  GOneWayCoercible (M1 i t f) (M1 i' t' f')++instance+  (GOneWayCoercible f f', GOneWayCoercible g g') =>+  GOneWayCoercible (f :*: g) (f' :*: g')++instance+  (OneWayCoercible a a', OneWayCoercible b b') =>+  OneWayCoercible (a' -> b) (a -> b')+  where+  oneWayCoercibleImpl = case oneWayCoercion @a @a' of+    MkOneWayCoercion Coercion -> case oneWayCoercion @b @b' of+      MkOneWayCoercion Coercion ->+        MkOneWayCoercibleD (MkOneWayCoercion Coercion)