polysemy-0.5.0.0: test/TypeErrors.hs
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
module TypeErrors where
-- $setup
-- >>> default ()
-- >>> :m +Polysemy
-- >>> :m +Polysemy.Output
-- >>> :m +Polysemy.Reader
-- >>> :m +Polysemy.Resource
-- >>> :m +Polysemy.State
-- >>> :m +Polysemy.Trace
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- 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 = ()
--------------------------------------------------------------------------------
-- |
-- TODO(sandy): should this mention 'Reader i' or just 'Reader'?
--
-- >>> :{
-- interpret @Reader $ \case
-- Ask -> undefined
-- :}
-- ...
-- ... 'Reader i' is higher-order, but 'interpret' can help only
-- ... with first-order effects.
-- ...
-- ... 'interpretH' instead.
-- ...
interpretBadFirstOrder = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- runFoldMapOutput
-- :: forall o m r a
-- . Monoid m
-- => (o -> m)
-- -> Sem (Output o ': r) a
-- -> Sem r (m, a)
-- runFoldMapOutput f = runState mempty . reinterpret $ \case
-- Output o -> modify (`mappend` f o)
-- :}
-- ...
-- ... Probable cause: ...reinterpret... is applied to too few arguments
-- ...
tooFewArgumentsReinterpret = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- 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''' = runTraceIO foo''
-- in runM foo'''
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... add (Member (Lift IO) '[]) ...
-- ...
--
-- PROBLEM: We're trying to run more effects than exist in the eff row. This is
-- indeed a problem, but the error message isn't helpful.
--
-- SOLUTION: Add a special case to `AmbiguousSend` when `r ~ '[]`.
runningTooManyEffects'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- foo :: Sem (State Int ': r) ()
-- foo = put ()
-- :}
-- ...
-- ... Ambiguous use of effect 'State'
-- ...
-- ... (Member (State ()) State Int : r) ...
-- ...
--
-- PROBLEM: There should be parentheses around `State Int : r`
--
-- SOLUTION: Emit parens only when the effect row is of the form `e1 ': ...`
missingParens'WRONG = ()
--------------------------------------------------------------------------------
-- |
-- >>> :{
-- let foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- :}
-- ...
-- ... Ambiguous use of effect 'Lift'
-- ...
-- ... (Member (Lift IO) r0) ...
-- ...
-- ... Could not deduce: (Member Resource r1)
-- ...
--
-- PROBLEM: This error is totally bogus. We forgot to give an argument to
-- 'runResourceInIO'. For comparison, the standard error GHC gives in this case
-- is significantly more helpful:
--
-- <interactive>:192:13: error:
-- • Couldn't match expected type ‘Sem '[Lift m] a’
-- with actual type ‘Sem (Resource : r0) a0 -> Sem r0 a0’
-- • Probable cause: ‘runResourceInIO’ is applied to too few arguments
-- In the second argument of ‘($)’, namely ‘runResourceInIO foo’
-- In the expression: runM $ runResourceInIO foo
-- In the expression:
-- let
-- foo :: Member Resource r => Sem r ()
-- foo = undefined
-- in runM $ runResourceInIO foo
-- • Relevant bindings include
-- it :: m a (bound at <interactive>:190:2)
-- <interactive>:192:29: error:
-- • Couldn't match expected type ‘Sem r0 x -> IO x’
-- with actual type ‘Sem r1 ()’
-- • In the first argument of ‘runResourceInIO’, namely ‘foo’
-- In the second argument of ‘($)’, namely ‘runResourceInIO foo’
-- In the expression: runM $ runResourceInIO foo
--
--
-- SOLUTION: Honestly I'm not sure!
missingArgumentToRunResourceInIO'WRONG = ()