lens-3.9: src/Control/Lens/Internal/Getter.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : Control.Lens.Internal.Getter
-- Copyright : (C) 2012-2013 Edward Kmett
-- License : BSD-style (see the file LICENSE)
-- Maintainer : Edward Kmett <ekmett@gmail.com>
-- Stability : provisional
-- Portability : non-portable
--
----------------------------------------------------------------------------
module Control.Lens.Internal.Getter
(
-- * Internal Classes
Gettable
-- ** Getters
, coerce
, noEffect
, Accessor(..)
) where
import Control.Applicative
import Data.Functor.Apply
import Data.Functor.Contravariant
import Data.Semigroup
import Data.Void
-- | This class is provided mostly for backwards compatibility with lens 3.8,
-- but it can also shorten type signatures.
class (Contravariant f, Functor f) => Gettable f
instance (Contravariant f, Functor f) => Gettable f
-------------------------------------------------------------------------------
-- Gettables & Accessors
-------------------------------------------------------------------------------
-- | This Generalizes 'Const' so we can apply simple 'Applicative'
-- transformations to it and so we can get nicer error messages.
--
-- A 'Functor' you can 'coerce' ignores its argument, which it carries solely as a
-- phantom type parameter.
--
-- By the 'Functor' and 'Contravariant' laws, an instance of 'Gettable' will necessarily satisfy:
--
-- @'id' = 'fmap' f = 'coerce' = 'contramap' g@
coerce :: (Contravariant f, Functor f) => f a -> f b
coerce a = absurd <$> contramap absurd a
{-# INLINE coerce #-}
-- | The 'mempty' equivalent for a 'Gettable' 'Applicative' 'Functor'.
noEffect :: (Contravariant f, Applicative f) => f a
noEffect = coerce $ pure ()
{-# INLINE noEffect #-}
-------------------------------------------------------------------------------
-- Accessors
-------------------------------------------------------------------------------
-- | Used instead of 'Const' to report
--
-- @No instance for ('Control.Lens.Setter.Internal.Settable' 'Accessor')@
--
-- when the user attempts to misuse a 'Control.Lens.Setter.Setter' as a
-- 'Control.Lens.Getter.Getter', rather than a monolithic unification error.
newtype Accessor r a = Accessor { runAccessor :: r }
instance Functor (Accessor r) where
fmap _ (Accessor m) = Accessor m
{-# INLINE fmap #-}
instance Contravariant (Accessor r) where
contramap _ (Accessor m) = Accessor m
{-# INLINE contramap #-}
instance Semigroup r => Apply (Accessor r) where
Accessor a <.> Accessor b = Accessor (a <> b)
{-# INLINE (<.>) #-}
instance Monoid r => Applicative (Accessor r) where
pure _ = Accessor mempty
{-# INLINE pure #-}
Accessor a <*> Accessor b = Accessor (mappend a b)
{-# INLINE (<*>) #-}