Change LastMember to cooperate better with rigid vars and local dicts

The use of a closed type family works well when the entire effect list
is known, but when it’s quantified over, the closed type family gets
stuck (since the effect list is rigid). Sometimes this is okay, since it
simply means the LastMember constraint is insoluble, but can be
satisfied if an explicit constraint brings a local LastMember dictionary
into scope. Performing the recursion directly in the instance avoids
this problem, though it does require overlapping instances.

fixes #6
This commit is contained in:
Alexis King 2018-02-20 10:35:14 -08:00
parent a2ae7109ad
commit 99e26fae04

View File

@ -61,10 +61,6 @@ type family Members effs effs' :: Constraint where
Members (eff ': effs) effs' = (Member eff effs', Members effs effs')
Members '[] effs' = ()
type family Last effs where
Last (eff ': '[]) = eff
Last (_ ': effs) = Last effs
-- | Like 'Member', @'LastMember' eff effs@ is a constraint that requires that
-- @eff@ is in the type-level list @effs@. However, /unlike/ 'Member',
-- 'LastMember' requires @m@ be the __final__ effect in @effs@.
@ -74,5 +70,6 @@ type family Last effs where
-- in combination with 'Control.Monad.Freer.sendM' or
-- 'Control.Monad.Base.liftBase' to embed ordinary monadic effects within an
-- 'Control.Monad.Freer.Eff' computation.
class (Member m effs, m ~ Last effs) => LastMember m effs | effs -> m
instance (Member m effs, m ~ Last effs) => LastMember m effs
class Member m effs => LastMember m effs | effs -> m
instance {-# OVERLAPPABLE #-} LastMember m effs => LastMember m (eff ': effs)
instance LastMember m (m ': '[])