Skip to content

Commit

Permalink
Work around bizarre GHC 7.10 Coercible bug
Browse files Browse the repository at this point in the history
After generalizing the type of `(#.)` in `Profunctor`, the GHC 7.10
build started experiencing errors like:

    Couldn't match representation of type ‘Zoomed m (c, w) t’
                             with that of ‘Zoomed m (c, w) t’

To make things more fun, this _only_ affects GHC 7.10. I opted for
the simplest workaround, which was to define a type-restricted
version of `(#.)` which restores the behavior of the old version of
`(#.)`.
  • Loading branch information
RyanGlScott committed Jul 3, 2018
1 parent 9d4ecf2 commit cde2fc3
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
14 changes: 13 additions & 1 deletion src/Control/Lens/Internal/Coerce.hs
Expand Up @@ -17,13 +17,17 @@
-- Portability : non-portable
--
-- This module provides a shim around 'coerce' that defaults to 'unsafeCoerce'
-- on GHC < 7.8
-- on GHC < 7.8. It also exposes a type-restricted version of '(#.)' that
-- works around a bizarre GHC 7.10–specific bug.
-----------------------------------------------------------------------------
module Control.Lens.Internal.Coerce
( coerce
, coerce'
, (#..)
) where

import Data.Profunctor.Unsafe

#ifdef USE_COERCE

import Data.Coerce
Expand All @@ -32,6 +36,10 @@ coerce' :: forall a b. Coercible a b => b -> a
coerce' = coerce (id :: a -> a)
{-# INLINE coerce' #-}

(#..) :: (Profunctor p, Coercible c b) => (b -> c) -> p a b -> p a c
(#..) = (#.)
{-# INLINE (#..) #-}

#else

import Unsafe.Coerce
Expand All @@ -41,4 +49,8 @@ coerce = unsafeCoerce
coerce' = unsafeCoerce
{-# INLINE coerce #-}
{-# INLINE coerce' #-}

(#..) :: Profunctor p => (b -> c) -> p a b -> p a c
(#..) = (#.)
{-# INLINE (#..) #-}
#endif
13 changes: 7 additions & 6 deletions src/Control/Lens/Zoom.hs
Expand Up @@ -32,6 +32,7 @@ module Control.Lens.Zoom
) where

import Control.Lens.Getter
import Control.Lens.Internal.Coerce
import Control.Lens.Internal.Zoom
import Control.Lens.Type
import Control.Monad
Expand Down Expand Up @@ -173,31 +174,31 @@ instance (Monoid w, Monad z) => Zoom (Lazy.RWST r w s z) (Lazy.RWST r w t z) s t
{-# INLINE zoom #-}

instance (Monoid w, Zoom m n s t) => Zoom (Strict.WriterT w m) (Strict.WriterT w n) s t where
zoom l = Strict.WriterT . zoom (\afb -> unfocusingPlus #. l (FocusingPlus #. afb)) . Strict.runWriterT
zoom l = Strict.WriterT . zoom (\afb -> unfocusingPlus #.. l (FocusingPlus #.. afb)) . Strict.runWriterT
{-# INLINE zoom #-}

instance (Monoid w, Zoom m n s t) => Zoom (Lazy.WriterT w m) (Lazy.WriterT w n) s t where
zoom l = Lazy.WriterT . zoom (\afb -> unfocusingPlus #. l (FocusingPlus #. afb)) . Lazy.runWriterT
zoom l = Lazy.WriterT . zoom (\afb -> unfocusingPlus #.. l (FocusingPlus #.. afb)) . Lazy.runWriterT
{-# INLINE zoom #-}

instance Zoom m n s t => Zoom (ListT m) (ListT n) s t where
zoom l = ListT . zoom (\afb -> unfocusingOn . l (FocusingOn . afb)) . runListT
{-# INLINE zoom #-}

instance Zoom m n s t => Zoom (MaybeT m) (MaybeT n) s t where
zoom l = MaybeT . liftM getMay . zoom (\afb -> unfocusingMay #. l (FocusingMay #. afb)) . liftM May . runMaybeT
zoom l = MaybeT . liftM getMay . zoom (\afb -> unfocusingMay #.. l (FocusingMay #.. afb)) . liftM May . runMaybeT
{-# INLINE zoom #-}

instance (Error e, Zoom m n s t) => Zoom (ErrorT e m) (ErrorT e n) s t where
zoom l = ErrorT . liftM getErr . zoom (\afb -> unfocusingErr #. l (FocusingErr #. afb)) . liftM Err . runErrorT
zoom l = ErrorT . liftM getErr . zoom (\afb -> unfocusingErr #.. l (FocusingErr #.. afb)) . liftM Err . runErrorT
{-# INLINE zoom #-}

instance Zoom m n s t => Zoom (ExceptT e m) (ExceptT e n) s t where
zoom l = ExceptT . liftM getErr . zoom (\afb -> unfocusingErr #. l (FocusingErr #. afb)) . liftM Err . runExceptT
zoom l = ExceptT . liftM getErr . zoom (\afb -> unfocusingErr #.. l (FocusingErr #.. afb)) . liftM Err . runExceptT
{-# INLINE zoom #-}

instance (Functor f, Zoom m n s t) => Zoom (FreeT f m) (FreeT f n) s t where
zoom l = FreeT . liftM (fmap $ zoom l) . liftM getFreed . zoom (\afb -> unfocusingFree #. l (FocusingFree #. afb)) . liftM Freed . runFreeT
zoom l = FreeT . liftM (fmap $ zoom l) . liftM getFreed . zoom (\afb -> unfocusingFree #.. l (FocusingFree #.. afb)) . liftM Freed . runFreeT

------------------------------------------------------------------------------
-- Magnify
Expand Down

0 comments on commit cde2fc3

Please sign in to comment.