packages feed

polysemy 1.6.0.0 → 1.7.0.0

raw patch · 11 files changed

+119/−279 lines, 11 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Polysemy: type Member e r = MemberNoError e r
- Polysemy: type MemberWithError e r = (MemberNoError e r, WhenStuck (LocateEffect e r) (AmbiguousSend e r))
- Polysemy.Internal: type Member e r = MemberNoError e r
- Polysemy.Internal: type MemberWithError e r = (MemberNoError e r, WhenStuck (LocateEffect e r) (AmbiguousSend e r))
- Polysemy.Internal.CustomErrors: type AmbiguousSend e r = (IfStuck r (AmbiguousSendError 'TyVarR r e) (Pure (AmbiguousSendError (UnstuckRState r) r e)))
- Polysemy.Internal.Union: [Here] :: ElemOf e (e : r)
- Polysemy.Internal.Union: [There] :: ElemOf e r -> ElemOf e (e' : r)
- Polysemy.Internal.Union: instance forall a (e :: a) (r :: [a]). (Data.Typeable.Internal.Typeable e, Polysemy.Internal.Union.KnownRow r) => Polysemy.Internal.Union.KnownRow (e : r)
- Polysemy.Internal.Union: instance forall a (t :: a) (z :: [a]) (_1 :: a). Polysemy.Internal.Union.Find t z => Polysemy.Internal.Union.Find t (_1 : z)
- Polysemy.Internal.Union: instance forall a (t :: a) (z :: [a]). Polysemy.Internal.Union.Find t (t : z)
- Polysemy.Internal.Union: type Member e r = MemberNoError e r
- Polysemy.Internal.Union: type MemberWithError e r = (MemberNoError e r, WhenStuck (LocateEffect e r) (AmbiguousSend e r))
- Polysemy.Membership: [Here] :: ElemOf e (e : r)
- Polysemy.Membership: [There] :: ElemOf e r -> ElemOf e (e' : r)
+ Polysemy: class Member (t :: Effect) (r :: EffectRow)
+ Polysemy.AtomicState: evalAtomicStateViaState :: s -> Sem (AtomicState s : r) a -> Sem r a
+ Polysemy.AtomicState: execAtomicStateViaState :: s -> Sem (AtomicState s : r) a -> Sem r s
+ Polysemy.AtomicState: runAtomicStateViaState :: s -> Sem (AtomicState s : r) a -> Sem r (s, a)
+ Polysemy.Internal: class Member (t :: Effect) (r :: EffectRow)
+ Polysemy.Internal.Union: class Member (t :: Effect) (r :: EffectRow)
+ Polysemy.Internal.Union: instance Polysemy.Internal.Union.Member t (t : z)
+ Polysemy.Internal.Union: instance Polysemy.Internal.Union.Member t z => Polysemy.Internal.Union.Member t (_1 : z)
+ Polysemy.Internal.Union: instance forall k (e :: k) (r :: [k]). (Data.Typeable.Internal.Typeable e, Polysemy.Internal.Union.KnownRow r) => Polysemy.Internal.Union.KnownRow (e : r)
+ Polysemy.Internal.Union: pattern There :: () => r' ~ (e' : r) => ElemOf e r -> ElemOf e r'
+ Polysemy.Membership: pattern There :: () => r' ~ (e' : r) => ElemOf e r -> ElemOf e r'
- Polysemy.Async: async :: forall r_aqjA a_Xqer. MemberWithError Async r_aqjA => Sem r_aqjA a_Xqer -> Sem r_aqjA (Async (Maybe a_Xqer))
+ Polysemy.Async: async :: forall r_apUO a_XpPy. Member Async r_apUO => Sem r_apUO a_XpPy -> Sem r_apUO (Async (Maybe a_XpPy))
- Polysemy.Async: await :: forall r_aqjC a_aqer. MemberWithError Async r_aqjC => Async a_aqer -> Sem r_aqjC a_aqer
+ Polysemy.Async: await :: forall r_apUQ a_apPy. Member Async r_apUQ => Async a_apPy -> Sem r_apUQ a_apPy
- Polysemy.Async: cancel :: forall r_aqjE a_Xqeu. MemberWithError Async r_aqjE => Async a_Xqeu -> Sem r_aqjE ()
+ Polysemy.Async: cancel :: forall r_apUS a_XpPB. Member Async r_apUS => Async a_XpPB -> Sem r_apUS ()
- Polysemy.Error: catch :: forall e_arnn r_arph a_arnp. MemberWithError (Error e_arnn) r_arph => Sem r_arph a_arnp -> (e_arnn -> Sem r_arph a_arnp) -> Sem r_arph a_arnp
+ Polysemy.Error: catch :: forall e_aqKz r_aqMt a_aqKB. Member (Error e_aqKz) r_aqMt => Sem r_aqMt a_aqKB -> (e_aqKz -> Sem r_aqMt a_aqKB) -> Sem r_aqMt a_aqKB
- Polysemy.Error: throw :: forall e_arnk r_arpf a_arnm. MemberWithError (Error e_arnk) r_arpf => e_arnk -> Sem r_arpf a_arnm
+ Polysemy.Error: throw :: forall e_aqKw r_aqMr a_aqKy. Member (Error e_aqKw) r_aqMr => e_aqKw -> Sem r_aqMr a_aqKy
- Polysemy.Input: input :: forall i_aDsG r_aDty. MemberWithError (Input i_aDsG) r_aDty => Sem r_aDty i_aDsG
+ Polysemy.Input: input :: forall i_aBcZ r_aBdR. Member (Input i_aBcZ) r_aBdR => Sem r_aBdR i_aBcZ
- Polysemy.Internal.TH.Common: getEffectMetadata :: Name -> Q (Name, [ConLiftInfo])
+ Polysemy.Internal.TH.Common: getEffectMetadata :: Name -> Q [ConLiftInfo]
- Polysemy.Internal.Union: data ElemOf e r
+ Polysemy.Internal.Union: data ElemOf (e :: k) (r :: [k])
- Polysemy.Internal.Writer: listen :: forall o_audN r_augc a_XudQ. MemberWithError (Writer o_audN) r_augc => Sem r_augc a_XudQ -> Sem r_augc (o_audN, a_XudQ)
+ Polysemy.Internal.Writer: listen :: forall o_at4Q r_at7f a_Xt4T. Member (Writer o_at4Q) r_at7f => Sem r_at7f a_Xt4T -> Sem r_at7f (o_at4Q, a_Xt4T)
- Polysemy.Internal.Writer: pass :: forall o_audR r_auge a_audS. MemberWithError (Writer o_audR) r_auge => Sem r_auge (o_audR -> o_audR, a_audS) -> Sem r_auge a_audS
+ Polysemy.Internal.Writer: pass :: forall o_at4U r_at7h a_at4V. Member (Writer o_at4U) r_at7h => Sem r_at7h (o_at4U -> o_at4U, a_at4V) -> Sem r_at7h a_at4V
- Polysemy.Internal.Writer: tell :: forall o_audL r_auga. MemberWithError (Writer o_audL) r_auga => o_audL -> Sem r_auga ()
+ Polysemy.Internal.Writer: tell :: forall o_at4O r_at7d. Member (Writer o_at4O) r_at7d => o_at4O -> Sem r_at7d ()
- Polysemy.Membership: data ElemOf e r
+ Polysemy.Membership: data ElemOf (e :: k) (r :: [k])
- Polysemy.Output: output :: forall o_aBL7 r_aBLW. MemberWithError (Output o_aBL7) r_aBLW => o_aBL7 -> Sem r_aBLW ()
+ Polysemy.Output: output :: forall o_azFj r_azG8. Member (Output o_azFj) r_azG8 => o_azFj -> Sem r_azG8 ()
- Polysemy.Reader: ask :: forall i_aDRY r_aDTv. MemberWithError (Reader i_aDRY) r_aDTv => Sem r_aDTv i_aDRY
+ Polysemy.Reader: ask :: forall i_aBxZ r_aBzw. Member (Reader i_aBxZ) r_aBzw => Sem r_aBzw i_aBxZ
- Polysemy.Reader: local :: forall i_aDS0 r_aDTw a_aDS2. MemberWithError (Reader i_aDS0) r_aDTw => (i_aDS0 -> i_aDS0) -> Sem r_aDTw a_aDS2 -> Sem r_aDTw a_aDS2
+ Polysemy.Reader: local :: forall i_aBy1 r_aBzx a_aBy3. Member (Reader i_aBy1) r_aBzx => (i_aBy1 -> i_aBy1) -> Sem r_aBzx a_aBy3 -> Sem r_aBzx a_aBy3
- Polysemy.Resource: bracket :: forall r_ayl2 a_XyiM c_XyiO b_ayiN. MemberWithError Resource r_ayl2 => Sem r_ayl2 a_XyiM -> (a_XyiM -> Sem r_ayl2 c_XyiO) -> (a_XyiM -> Sem r_ayl2 b_ayiN) -> Sem r_ayl2 b_ayiN
+ Polysemy.Resource: bracket :: forall r_awGv a_XwEf c_XwEh b_awEg. Member Resource r_awGv => Sem r_awGv a_XwEf -> (a_XwEf -> Sem r_awGv c_XwEh) -> (a_XwEf -> Sem r_awGv b_awEg) -> Sem r_awGv b_awEg
- Polysemy.Resource: bracketOnError :: forall r_ayl6 a_XyiQ c_XyiS b_ayiR. MemberWithError Resource r_ayl6 => Sem r_ayl6 a_XyiQ -> (a_XyiQ -> Sem r_ayl6 c_XyiS) -> (a_XyiQ -> Sem r_ayl6 b_ayiR) -> Sem r_ayl6 b_ayiR
+ Polysemy.Resource: bracketOnError :: forall r_awGz a_XwEj c_XwEl b_awEk. Member Resource r_awGz => Sem r_awGz a_XwEj -> (a_XwEj -> Sem r_awGz c_XwEl) -> (a_XwEj -> Sem r_awGz b_awEk) -> Sem r_awGz b_awEk
- Polysemy.State: get :: forall s_aA38 r_aA4y. MemberWithError (State s_aA38) r_aA4y => Sem r_aA4y s_aA38
+ Polysemy.State: get :: forall s_ayaT r_aycj. Member (State s_ayaT) r_aycj => Sem r_aycj s_ayaT
- Polysemy.State: put :: forall s_aA3a r_aA4z. MemberWithError (State s_aA3a) r_aA4z => s_aA3a -> Sem r_aA4z ()
+ Polysemy.State: put :: forall s_ayaV r_ayck. Member (State s_ayaV) r_ayck => s_ayaV -> Sem r_ayck ()
- Polysemy.Trace: trace :: forall r_aFWb. MemberWithError Trace r_aFWb => String -> Sem r_aFWb ()
+ Polysemy.Trace: trace :: forall r_aDmP. Member Trace r_aDmP => String -> Sem r_aDmP ()
- Polysemy.View: see :: forall v_aGvo r_aGwg. MemberWithError (View v_aGvo) r_aGwg => Sem r_aGwg v_aGvo
+ Polysemy.View: see :: forall v_aDOs r_aDPk. Member (View v_aDOs) r_aDPk => Sem r_aDPk v_aDOs
- Polysemy.Writer: listen :: forall o_audN r_augc a_XudQ. MemberWithError (Writer o_audN) r_augc => Sem r_augc a_XudQ -> Sem r_augc (o_audN, a_XudQ)
+ Polysemy.Writer: listen :: forall o_at4Q r_at7f a_Xt4T. Member (Writer o_at4Q) r_at7f => Sem r_at7f a_Xt4T -> Sem r_at7f (o_at4Q, a_Xt4T)
- Polysemy.Writer: pass :: forall o_audR r_auge a_audS. MemberWithError (Writer o_audR) r_auge => Sem r_auge (o_audR -> o_audR, a_audS) -> Sem r_auge a_audS
+ Polysemy.Writer: pass :: forall o_at4U r_at7h a_at4V. Member (Writer o_at4U) r_at7h => Sem r_at7h (o_at4U -> o_at4U, a_at4V) -> Sem r_at7h a_at4V
- Polysemy.Writer: tell :: forall o_audL r_auga. MemberWithError (Writer o_audL) r_auga => o_audL -> Sem r_auga ()
+ Polysemy.Writer: tell :: forall o_at4O r_at7d. Member (Writer o_at4O) r_at7d => o_at4O -> Sem r_at7d ()

Files

ChangeLog.md view
@@ -2,6 +2,30 @@  ## Unreleased +### Breaking Changes++### Other Changes+++## 1.7.0.0 (2021-11-16)++### Breaking Changes++* Added interpreters for `AtomicState` that run in terms of `State`.+* Removed `MemberWithError`+* Removed `DefiningModule`++### Other Changes++* The internal `ElemOf` proof is now implemented as an unsafe integer,+    significantly cutting down on generated core.+* Polysemy no longer emits custom type errors for ambiguous effect actions.+    These have long been rendered moot by `polysemy-plugin`, and the cases that+    they still exist are usually overeager (and wrong.)+* As a result, the core produced by `polysemy` is significantly smaller.+    Programs should see a reduction of ~20% in terms and types, and ~60% in+    coercions.+ ## 1.6.0.0 (2021-07-12)  ### Breaking Changes@@ -38,7 +62,7 @@   ([#337](https://github.com/polysemy-research/polysemy/pull/337), [#382](https://github.com/polysemy-research/polysemy/pull/382)) - Restrict the existentially quantified monad in a `Weaving` to `Sem r`   ([#333](https://github.com/polysemy-research/polysemy/pull/333), thanks to @A1kmm)-- Added `raise2Under` and `raise3Under` +- Added `raise2Under` and `raise3Under`   ([#369](https://github.com/polysemy-research/polysemy/pull/369)) - Added `Raise` and `Subsume`   ([#370](https://github.com/polysemy-research/polysemy/pull/370))
README.md view
@@ -76,7 +76,7 @@  ```haskell {-# LANGUAGE TemplateHaskell, LambdaCase, BlockArguments, GADTs-           , FlexibleContexts, TypeOperators, DataKinds, PolyKinds #-}+           , FlexibleContexts, TypeOperators, DataKinds, PolyKinds, ScopedTypeVariables #-}  import Polysemy import Polysemy.Input@@ -194,12 +194,6 @@     interpret       $ \case ```--Likewise it will give you tips on what to do if you forget a `TypeApplication`-or forget to handle an effect.--Don't like helpful errors? That's OK too - just flip the `error-messages`-flag and enjoy the raw, unadulterated fury of the typesystem.  ## Necessary Language Extensions 
polysemy.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           polysemy-version:        1.6.0.0+version:        1.7.0.0 synopsis:       Higher-order, low-boilerplate free monads. description:    Please see the README on GitHub at <https://github.com/polysemy-research/polysemy#readme> category:       Language@@ -13,7 +13,7 @@ bug-reports:    https://github.com/polysemy-research/polysemy/issues author:         Sandy Maguire maintainer:     sandy@sandymaguire.me-copyright:      2019 Sandy Maguire+copyright:      2019-2021 Sandy Maguire license:        BSD3 license-file:   LICENSE build-type:     Custom@@ -36,11 +36,6 @@   manual: True   default: False -flag error-messages-  description: Provide custom error messages-  manual: True-  default: True- library   exposed-modules:       Polysemy@@ -132,10 +127,6 @@   if impl(ghc < 8.2.2)     build-depends:         unsupported-ghc-version >1 && <1-  if flag(error-messages)-    cpp-options: -DCABAL_SERIOUSLY_CMON_MATE-  else-    cpp-options: -DNO_ERROR_MESSAGES   default-language: Haskell2010  test-suite polysemy-test
src/Polysemy.hs view
@@ -2,7 +2,6 @@   ( -- * Core Types     Sem ()   , Member-  , MemberWithError   , Members      -- * Running Sem
src/Polysemy/AtomicState.hs view
@@ -18,6 +18,9 @@   , runAtomicStateTVar   , atomicStateToIO   , atomicStateToState+  , runAtomicStateViaState+  , evalAtomicStateViaState+  , execAtomicStateViaState   ) where  @@ -170,3 +173,43 @@     return a   AtomicGet -> get {-# INLINE atomicStateToState #-}++------------------------------------------------------------------------------+-- | Run an 'AtomicState' with local state semantics, discarding+-- the notion of atomicity, by transforming it into 'State' and running it+-- with the provided initial state.+--+--+-- @since v1.7.0.0+runAtomicStateViaState :: s+                       -> Sem (AtomicState s ': r) a+                       -> Sem r (s, a)+runAtomicStateViaState s =+  runState s . atomicStateToState . raiseUnder+{-# INLINE runAtomicStateViaState #-}++------------------------------------------------------------------------------+-- | Evaluate an 'AtomicState' with local state semantics, discarding+-- the notion of atomicity, by transforming it into 'State' and running it+-- with the provided initial state.+--+-- @since v1.7.0.0+evalAtomicStateViaState :: s+                        -> Sem (AtomicState s ': r) a+                        -> Sem r a+evalAtomicStateViaState s =+  evalState s . atomicStateToState . raiseUnder+{-# INLINE evalAtomicStateViaState #-}++------------------------------------------------------------------------------+-- | Execute an 'AtomicState' with local state semantics, discarding+-- the notion of atomicity, by transforming it into 'State' and running it+-- with the provided initial state.+--+-- @since v1.7.0.0+execAtomicStateViaState :: s+                        -> Sem (AtomicState s ': r) a+                        -> Sem r s+execAtomicStateViaState s =+  execState s . atomicStateToState . raiseUnder+{-# INLINE execAtomicStateViaState #-}
src/Polysemy/Internal.hs view
@@ -11,7 +11,6 @@ module Polysemy.Internal   ( Sem (..)   , Member-  , MemberWithError   , Members   , send   , sendUsing
src/Polysemy/Internal/CustomErrors.hs view
@@ -7,12 +7,8 @@ {-# OPTIONS_HADDOCK not-home #-}  module Polysemy.Internal.CustomErrors-  ( AmbiguousSend-  , WhenStuck+  ( WhenStuck   , FirstOrder-  , UnhandledEffect-  , DefiningModule-  , DefiningModuleForEffect   , type (<>)   , type (%)   ) where@@ -25,18 +21,6 @@ import Type.Errors hiding (IfStuck, WhenStuck, UnlessStuck)  ---------------------------------------------------------------------------------- | The module this effect was originally defined in. This type family is used--- only for providing better error messages.------ Calls to 'Polysemy.Internal.TH.Effect.makeSem' will automatically give--- instances of 'DefiningModule'.-type family DefiningModule (t :: k) :: Symbol--type family DefiningModuleForEffect (e :: k) :: Symbol where-  DefiningModuleForEffect (e a) = DefiningModuleForEffect e-  DefiningModuleForEffect e     = DefiningModule e- -- These are taken from type-errors-pretty because it's not in stackage for 9.0.1 -- See https://github.com/polysemy-research/polysemy/issues/401 type family ToErrorMessage (t :: k) :: ErrorMessage where@@ -77,51 +61,6 @@   ShowRQuoted 'ConsR  r = ShowTypeBracketed r  -type AmbigousEffectMessage (rstate :: EffectRowCtor)-                           (r :: EffectRow)-                           (e :: k)-                           (t :: Effect)-                           (vs :: [Type])-  = "Ambiguous use of effect '" <> e <> "'"-  % "Possible fix:"-  % "  add (Member (" <> t <> ") " <> ShowRQuoted rstate r <> ") to the context of "-  % "    the type signature"-  % "If you already have the constraint you want, instead"-  % "  add a type application to specify"-  % "    " <> PrettyPrintList vs <> " directly, or activate polysemy-plugin which"-  % "      can usually infer the type correctly."--type AmbiguousSend e r =-      (IfStuck r-        (AmbiguousSendError 'TyVarR r e)-        (Pure (AmbiguousSendError (UnstuckRState r) r e)))---type family AmbiguousSendError rstate r e where-  AmbiguousSendError rstate r (e a b c d f) =-    TypeError (AmbigousEffectMessage rstate r e (e a b c d f) '[a, b c d f])--  AmbiguousSendError rstate r (e a b c d) =-    TypeError (AmbigousEffectMessage rstate r e (e a b c d) '[a, b c d])--  AmbiguousSendError rstate r (e a b c) =-    TypeError (AmbigousEffectMessage rstate r e (e a b c) '[a, b c])--  AmbiguousSendError rstate r (e a b) =-    TypeError (AmbigousEffectMessage rstate r e (e a b) '[a, b])--  AmbiguousSendError rstate r (e a) =-    TypeError (AmbigousEffectMessage rstate r e (e a) '[a])--  AmbiguousSendError rstate r e =-    TypeError-        ( "Could not deduce: (Member " <>  e <> " " <> ShowRQuoted rstate r <> ") "-        % "Fix:"-        % "  add (Member " <>  e <> " " <> r <> ") to the context of"-        % "    the type signature"-        )-- data FirstOrderErrorFcf :: k -> Symbol -> Exp Constraint type instance Eval (FirstOrderErrorFcf e fn) = $(te[t|     UnlessPhantom@@ -136,24 +75,6 @@ -- | This constraint gives helpful error messages if you attempt to use a -- first-order combinator with a higher-order type. type FirstOrder (e :: Effect) fn = UnlessStuck e (FirstOrderErrorFcf e fn)------------------------------------------------------------------------------------ | Unhandled effects-type UnhandledEffectMsg e-  = "Unhandled effect '" <> e <> "'"-  % "Probable fix:"-  % "  add an interpretation for '" <> e <> "'"--type CheckDocumentation e-  = "  If you are looking for inspiration, try consulting"-  % "    the documentation for module '" <> DefiningModuleForEffect e <> "'"--type family UnhandledEffect e where-  UnhandledEffect e =-    IfStuck (DefiningModule e)-            (TypeError (UnhandledEffectMsg e))-            (DoError (UnhandledEffectMsg e ':$$: CheckDocumentation e))   data DoError :: ErrorMessage -> Exp k
src/Polysemy/Internal/TH/Common.hs view
@@ -33,7 +33,7 @@ import           Language.Haskell.TH.Datatype import           Language.Haskell.TH.PprLib import           Polysemy.Internal (Sem, send)-import           Polysemy.Internal.Union (MemberWithError)+import           Polysemy.Internal.Union (Member)  #if __GLASGOW_HASKELL__ >= 804 import           Prelude hiding ((<>))@@ -71,11 +71,11 @@ ------------------------------------------------------------------------------ -- | Given an name of datatype or some of it's constructors/fields, return -- datatype's name together with info about it's constructors.-getEffectMetadata :: Name -> Q (Name, [ConLiftInfo])+getEffectMetadata :: Name -> Q [ConLiftInfo] getEffectMetadata type_name = do   dt_info  <- reifyDatatype type_name   cl_infos <- traverse makeCLInfo $ constructorName <$> datatypeCons dt_info-  pure (datatypeName dt_info, cl_infos)+  pure cl_infos   ------------------------------------------------------------------------------@@ -157,7 +157,7 @@ -- | @'makeMemberConstraint'' r type@ will produce a @Member type r@ -- constraint. makeMemberConstraint' :: Name -> Type -> Pred-makeMemberConstraint' r eff = classPred ''MemberWithError [eff, VarT r]+makeMemberConstraint' r eff = classPred ''Member [eff, VarT r]   ------------------------------------------------------------------------------
src/Polysemy/Internal/TH/Effect.hs view
@@ -32,7 +32,6 @@ import Control.Monad import Language.Haskell.TH import Language.Haskell.TH.Datatype-import Polysemy.Internal.CustomErrors (DefiningModule) import Polysemy.Internal.TH.Common  @@ -123,20 +122,11 @@ genFreer :: Bool -> Name -> Q [Dec] genFreer should_mk_sigs type_name = do   checkExtensions [ScopedTypeVariables, FlexibleContexts, DataKinds]-  (dt_name, cl_infos) <- getEffectMetadata type_name-  tyfams_on  <- isExtEnabled TypeFamilies-  def_mod_fi <- sequence [ tySynInstDCompat-                             ''DefiningModule-                             Nothing-                             [pure $ ConT dt_name]-                             (LitT . StrTyLit . loc_module <$> location)-                         | tyfams_on-                         ]+  cl_infos <- getEffectMetadata type_name   decs <- traverse (genDec should_mk_sigs) cl_infos    let sigs = if should_mk_sigs then genSig <$> cl_infos else []--  pure $ join $ def_mod_fi : sigs ++ decs+  pure $ join $ sigs ++ decs   ------------------------------------------------------------------------------
src/Polysemy/Internal/Union.hs view
@@ -6,10 +6,13 @@ {-# LANGUAGE FunctionalDependencies  #-} {-# LANGUAGE InstanceSigs            #-} {-# LANGUAGE MultiParamTypeClasses   #-}+{-# LANGUAGE PatternSynonyms         #-}+{-# LANGUAGE RoleAnnotations         #-} {-# LANGUAGE StrictData              #-} {-# LANGUAGE TypeFamilies            #-} {-# LANGUAGE UndecidableInstances    #-} {-# LANGUAGE UndecidableSuperClasses #-}+{-# LANGUAGE ViewPatterns            #-}  {-# OPTIONS_HADDOCK not-home #-} @@ -17,7 +20,6 @@   ( Union (..)   , Weaving (..)   , Member-  , MemberWithError   , weave   , hoist   -- * Building Unions@@ -33,7 +35,7 @@   , absurdU   , decompCoerce   -- * Witnesses-  , ElemOf (..)+  , ElemOf (Here, There)   , membership   , sameMember   -- * Checking membership@@ -53,10 +55,7 @@ import Polysemy.Internal.Kind import {-# SOURCE #-} Polysemy.Internal import Polysemy.Internal.Sing (SList (SEnd, SCons))--#ifndef NO_ERROR_MESSAGES-import Polysemy.Internal.CustomErrors-#endif+import Unsafe.Coerce (unsafeCoerce)   ------------------------------------------------------------------------------@@ -133,43 +132,7 @@   Union w $ Weaving e s (f' . nt) f v {-# INLINE hoist #-} - --------------------------------------------------------------------------------- | A proof that the effect @e@ is available somewhere inside of the effect--- stack @r@.-type Member e r = MemberNoError e r----------------------------------------------------------------------------------- | Like 'Member', but will produce an error message if the types are--- ambiguous. This is the constraint used for actions generated by--- 'Polysemy.makeSem'.------ /Be careful with this./ Due to quirks of 'GHC.TypeLits.TypeError',--- the custom error messages emitted by this can potentially override other,--- more helpful error messages.--- See the discussion in--- <https://github.com/polysemy-research/polysemy/issues/227 Issue #227>.------ @since 1.2.3.0-type MemberWithError e r =-  ( MemberNoError e r-#ifndef NO_ERROR_MESSAGES-    -- NOTE: The plugin explicitly pattern matches on-    -- `WhenStuck (LocateEffect _ r) _`, so if you change this, make sure to change-    -- the corresponding implementation in-    -- Polysemy.Plugin.Fundep.solveBogusError-  , WhenStuck (LocateEffect e r) (AmbiguousSend e r)-#endif-  )--type MemberNoError e r =-  ( Find e r-#ifndef NO_ERROR_MESSAGES-  , LocateEffect e r ~ '()-#endif-  )-------------------------------------------------------------------------------- -- | A proof that @e@ is an element of @r@. -- -- Due to technical reasons, @'ElemOf' e r@ is not powerful enough to@@ -177,12 +140,37 @@ -- into @r@ by using 'Polysemy.Internal.subsumeUsing'. -- -- @since 1.3.0.0-data ElemOf e r where-  -- | @e@ is located at the head of the list.-  Here  :: ElemOf e (e ': r)-  -- | @e@ is located somewhere in the tail of the list.-  There :: ElemOf e r -> ElemOf e (e' ': r)+type role ElemOf nominal nominal+newtype ElemOf (e :: k) (r :: [k]) = UnsafeMkElemOf Int +data MatchHere e r where+  MHYes :: MatchHere e (e ': r)+  MHNo  :: MatchHere e r++data MatchThere e r where+  MTYes :: ElemOf e r -> MatchThere e (e' ': r)+  MTNo  :: MatchThere e r++matchHere :: forall e r. ElemOf e r -> MatchHere e r+matchHere (UnsafeMkElemOf 0) = unsafeCoerce $ MHYes+matchHere _ = MHNo++matchThere :: forall e r. ElemOf e r -> MatchThere e r+matchThere (UnsafeMkElemOf 0) = MTNo+matchThere (UnsafeMkElemOf e) = unsafeCoerce $ MTYes $ UnsafeMkElemOf $ e - 1++pattern Here :: () => (r ~ (e ': r')) => ElemOf e r+pattern Here <- (matchHere -> MHYes)+  where+    Here = UnsafeMkElemOf 0++pattern There :: () => (r' ~ (e' ': r)) => ElemOf e r -> ElemOf e r'+pattern There e <- (matchThere -> MTYes e)+  where+    There (UnsafeMkElemOf e) = UnsafeMkElemOf $ e + 1++{-# COMPLETE Here, There #-}+ ------------------------------------------------------------------------------ -- | Checks if two membership proofs are equal. If they are, then that means -- that the effects for which membership is proven must also be equal.@@ -200,26 +188,15 @@   Nothing  ---------------------------------------------------------------------------------- | Used to detect ambiguous uses of effects. If @r@ isn't concrete,--- and we haven't been given @'LocateEffect' e r ~ '()@ from a--- @'Member' e r@ constraint, then @'LocateEffect' e r@ will get stuck.-type family LocateEffect (t :: k) (ts :: [k]) :: () where-#ifndef NO_ERROR_MESSAGES-  LocateEffect t '[] = UnhandledEffect t-#endif-  LocateEffect t (t ': ts) = '()-  LocateEffect t (u ': ts) = LocateEffect t ts--class Find (t :: k) (r :: [k]) where+class Member (t :: Effect) (r :: EffectRow) where   membership' :: ElemOf t r -instance {-# OVERLAPPING #-} Find t (t ': z) where+instance {-# OVERLAPPING #-} Member t (t ': z) where   membership' = Here   {-# INLINE membership' #-} -instance Find t z => Find t (_1 ': z) where-  membership' = There $ membership' @_ @t @z+instance Member t z => Member t (_1 ': z) where+  membership' = There $ membership' @t @z   {-# INLINE membership' #-}  ------------------------------------------------------------------------------@@ -305,20 +282,14 @@ -- | Retrieve the last effect in a 'Union'. extract :: Union '[e] m a -> Weaving e m a extract (Union Here a)   = a-#if __GLASGOW_HASKELL__ < 808-extract (Union (There g) _) = case g of {}-#endif+extract (Union (There _) _) = error "Unsafe use of UnsafeMkElemOf" {-# INLINE extract #-}   ------------------------------------------------------------------------------ -- | An empty union contains nothing, so this function is uncallable. absurdU :: Union '[] m a -> b-#if __GLASGOW_HASKELL__ < 808-absurdU (Union pr _) = case pr of {}-#else-absurdU = \case {}-#endif+absurdU (Union _ _) = error "Unsafe use of UnsafeMkElemOf"   ------------------------------------------------------------------------------
test/TypeErrors.hs view
@@ -16,36 +16,6 @@ -------------------------------------------------------------------------------- -- | -- >>> :{--- foo :: Sem r ()--- foo = put ()--- :}--- ...--- ... Ambiguous use of effect 'State'--- ...--- ... (Member (State ()) r) ...--- ...-ambiguousMonoState = ()-------------------------------------------------------------------------------------- |--- >>> :{--- foo :: Sem r ()--- foo = put 5--- :}--- ...--- ... Ambiguous use of effect 'State'--- ...--- ... (Member (State s0) r) ...--- ...--- ... 's0' directly...--- ...-ambiguousPolyState = ()-------------------------------------------------------------------------------------- |--- >>> :{ -- interpret @(Reader Bool) $ \case --   Ask -> undefined -- :}@@ -79,41 +49,6 @@ -------------------------------------------------------------------------------- -- | -- >>> :{--- let reinterpretScrub :: Sem (Output Int ': m) a -> Sem (State Bool ': Trace ': m) a---     reinterpretScrub = undefined---     foo :: Sem '[Output Int] ()---     foo = pure ()---     foo' = reinterpretScrub foo---     foo'' = runState True foo'---     foo''' = traceToIO foo''---  in runM foo'''--- :}--- ...--- ... Unhandled effect 'Embed IO'--- ...--- ... Expected... Sem '[Embed m] (Bool, ())--- ... Actual... Sem '[] (Bool, ())--- ...-runningTooManyEffects = ()-------------------------------------------------------------------------------------- |--- >>> :{--- foo :: Sem (State Int ': r) ()--- foo = put ()--- :}--- ...--- ... Ambiguous use of effect 'State'--- ...--- ... (Member (State ()) (State Int : r)) ...--- ...-ambiguousSendInConcreteR = ()-------------------------------------------------------------------------------------- |--- >>> :{ -- let foo :: Member Resource r => Sem r () --     foo = undefined --  in runM $ lowerResource foo@@ -124,31 +59,4 @@ -- ... Probable cause: ... is applied to too few arguments -- ... missingArgumentToRunResourceInIO = ()-------------------------------------------------------------------------------------- |--- >>> :{--- existsKV :: Member (State (Maybe Int)) r => Sem r Bool--- existsKV = isJust get--- :}--- ...--- ... Ambiguous use of effect 'State'--- ...------ NOTE: This is fixed by enabling the plugin!-missingFmap'PLUGIN = ()------------------------------------------------------------------------------------- |--- >>> :{--- foo :: Sem '[State Int, Embed IO] ()--- foo = output ()--- :}--- ...--- ... Unhandled effect 'Output ()'--- ...--- ... add an interpretation for 'Output ()'--- ...-missingEffectInStack'WRONG = ()