diff --git a/generic-lens-core/src/Data/Generics/Internal/Void.hs b/generic-lens-core/src/Data/Generics/Internal/Void.hs index 51a0a7d5..b02638ec 100644 --- a/generic-lens-core/src/Data/Generics/Internal/Void.hs +++ b/generic-lens-core/src/Data/Generics/Internal/Void.hs @@ -1,19 +1,24 @@ {-# LANGUAGE PolyKinds #-} -module Data.Generics.Internal.Void where +module Data.Generics.Internal.Void + ( -- $note + Void + , Void1 + , Void2 + ) where -{- - Note [Uncluttering type signatures] - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- +-- $note +-- = Uncluttering type signatures +-- +-- Because the various instances in the library always match (the Has* classes +-- are essentially glorified constraint synonyms), they get replaced with +-- their constraints, resulting in large, unreadable types. +-- +-- Writing an (overlapping instance) for this Void type means that the original +-- instance might not be the one selected, thus GHC leaves the constraints in +-- place until further information is provided, at which point the type +-- machinery has sufficient information to reduce to sensible types. - Because the various instances in the library always match (the Has* classes - are essentially glorified constraint synonyms), they get replaced with - their constraints, resulting in large, unreadable types. - - Writing an (overlapping instance) for this Void type means that the original - instance might not be the one selected, thus GHC leaves the constraints in - place until further information is provided, at which point the type - machinery has sufficient information to reduce to sensible types. --} data Void data Void1 a data Void2 a b diff --git a/generic-lens-core/src/Data/Generics/Product/#Positions.hs# b/generic-lens-core/src/Data/Generics/Product/#Positions.hs# deleted file mode 100644 index 0d64668a..00000000 --- a/generic-lens-core/src/Data/Generics/Product/#Positions.hs# +++ /dev/null @@ -1,154 +0,0 @@ -{-# LANGUAGE TypeInType #-} -{-# LANGUAGE PartialTypeSignatures #-} -{-# LANGUAGE AllowAmbiguousTypes #-} -{-# LANGUAGE ConstraintKinds #-} -{-# LANGUAGE DataKinds #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE FunctionalDependencies #-} -{-# LANGUAGE KindSignatures #-} -{-# LANGUAGE MultiParamTypeClasses #-} -{-# LANGUAGE PolyKinds #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TypeApplications #-} -{-# LANGUAGE TypeFamilies #-} -{-# LANGUAGE TypeOperators #-} -{-# LANGUAGE UndecidableInstances #-} - ------------------------------------------------------------------------------ --- | --- Module : Data.Generics.Product.Positions --- Copyright : (C) 2020 Csongor Kiss --- License : BSD3 --- Maintainer : Csongor Kiss --- Stability : experimental --- Portability : non-portable --- --- Derive positional product type getters and setters generically. --- ------------------------------------------------------------------------------ - -module Data.Generics.Product.Positions - ( -- *Lenses - - -- $setup - HasPosition (..) - , HasPosition' (..) - , HasPosition_ (..) - , HasPosition0 (..) - - , getPosition - , setPosition - ) where - -import Data.Generics.Internal.VL.Lens as VL -import Data.Generics.Internal.Void -import Data.Generics.Internal.Families -import Data.Generics.Product.Internal.Positions -import Data.Generics.Product.Internal.GLens -import Data.Generics.Internal.Errors - -import Data.Kind (Constraint, Type) -import Data.Type.Bool (type (&&)) -import GHC.Generics -import GHC.TypeLits (type (<=?), Nat, TypeError, ErrorMessage(..)) -import Data.Generics.Internal.Profunctor.Lens as P -import Data.Generics.Internal.Profunctor.Iso as P -import Data.Coerce - --- $setup --- == /Running example:/ --- --- >>> :set -XTypeApplications --- >>> :set -XDataKinds --- >>> :set -XDeriveGeneric --- >>> :set -XGADTs --- >>> :set -XFlexibleContexts --- >>> import GHC.Generics --- >>> :m +Data.Generics.Internal.VL.Lens --- >>> :m +Data.Function --- >>> :{ --- data Human = Human --- { name :: String --- , age :: Int --- , address :: String --- } --- deriving (Generic, Show) --- human :: Human --- human = Human "Tunyasz" 50 "London" --- :} - --- |Records that have a field at a given position. -class HasPosition (i :: Nat) s t a b | s i -> a, t i -> b, s i b -> t, t i a -> s where - -- |A lens that focuses on a field at a given position. Compatible with the - -- lens package's 'Control.Lens.Lens' type. - -- - -- >>> human ^. position @1 - -- "Tunyasz" - -- >>> human & position @3 .~ "Berlin" - -- Human {name = "Tunyasz", age = 50, address = "Berlin"} - -- - -- === /Type errors/ - -- - -- >>> human & position @4 .~ "Berlin" - -- ... - -- ... The type Human does not contain a field at position 4 - -- ... - position :: VL.Lens s t a b - -class HasPosition_ (i :: Nat) s t a b where - position_ :: VL.Lens s t a b - --- |Records that have a field at a given position. --- --- The difference between 'HasPosition' and 'HasPosition_' is similar to the --- one between 'Data.Generics.Product.Fields.HasField' and --- 'Data.Generics.Product.Fields.HasField_'. --- See 'Data.Generics.Product.Fields.HasField_'. -class HasPosition' (i :: Nat) s a | s i -> a where - position' :: VL.Lens s s a a - --- |Records that have a field at a given position. --- --- This class gives the minimal constraints needed to define this lens. --- For common uses, see 'HasPosition'. -class HasPosition0 (i :: Nat) s t a b where - position0 :: VL.Lens s t a b - --- | --- >>> getPosition @2 human --- 50 -getPosition :: forall i s a. HasPosition' i s a => s -> a -getPosition s = s ^. position' @i - --- | --- >>> setPosition @2 60 human --- Human {name = "Tunyasz", age = 60, address = "London"} -setPosition :: forall i s a. HasPosition' i s a => a -> s -> s -setPosition = VL.set (position' @i) - -instance Context' i s a => HasPosition' i s a where - position' f s = VL.ravel derived' f s - {-# INLINE position' #-} - -instance (Context i s t a b , HasPosition0 i s t a b) => HasPosition i s t a b where - position = position0 @i - {-# INLINE position #-} - --- | See Note [Uncluttering type signatures] --- >>> :t +d position --- position --- :: (HasPosition i s t a b, Functor f) => (a -> f b) -> s -> f t -instance {-# OVERLAPPING #-} HasPosition f (Void1 a) (Void1 b) a b where - position = undefined - -instance (Context_ i s t a b, HasPosition0 i s t a b) => HasPosition_ i s t a b where - position_ = position0 @i - {-# INLINE position_ #-} - -instance {-# OVERLAPPING #-} HasPosition_ f (Void1 a) (Void1 b) a b where - position_ = undefined - -instance Context0 i s t a b => HasPosition0 i s t a b where - position0 f s = VL.ravel derived0 f s - {-# INLINE position0 #-} diff --git a/generic-lens/generic-lens.cabal b/generic-lens/generic-lens.cabal index 6b58f358..acfddf31 100644 --- a/generic-lens/generic-lens.cabal +++ b/generic-lens/generic-lens.cabal @@ -101,5 +101,7 @@ test-suite doctests type: exitcode-stdio-1.0 ghc-options: -threaded main-is: doctest.hs - build-depends: base >4 && <5, doctest + build-depends: base >4 && <5 + , doctest + , lens hs-source-dirs: examples diff --git a/generic-lens/src/Data/Generics/Product/Fields.hs b/generic-lens/src/Data/Generics/Product/Fields.hs index 85777c7e..b88b24b6 100644 --- a/generic-lens/src/Data/Generics/Product/Fields.hs +++ b/generic-lens/src/Data/Generics/Product/Fields.hs @@ -155,7 +155,8 @@ instance (Core.Context field s t a b , HasField0 field s t a b) => HasField fiel -- instance {-# OVERLAPPING #-} HasField' field s a => HasField field s s a a where -- field f s = field' @field f s --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d field -- field -- :: (HasField field s t a b, Functor f) => (a -> f b) -> s -> f t diff --git a/generic-lens/src/Data/Generics/Product/Positions.hs b/generic-lens/src/Data/Generics/Product/Positions.hs index 3450e99c..feb3fc53 100644 --- a/generic-lens/src/Data/Generics/Product/Positions.hs +++ b/generic-lens/src/Data/Generics/Product/Positions.hs @@ -128,7 +128,8 @@ instance (Core.Context i s t a b , HasPosition0 i s t a b) => HasPosition i s t position = position0 @i {-# INLINE position #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d position -- position -- :: (HasPosition i s t a b, Functor f) => (a -> f b) -> s -> f t diff --git a/generic-lens/src/Data/Generics/Product/Subtype.hs b/generic-lens/src/Data/Generics/Product/Subtype.hs index 757fed8b..05229b44 100644 --- a/generic-lens/src/Data/Generics/Product/Subtype.hs +++ b/generic-lens/src/Data/Generics/Product/Subtype.hs @@ -117,14 +117,16 @@ instance Core.Context a b => Subtype b a where instance {-# OVERLAPPING #-} Subtype a a where super = id --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d super -- super -- :: (Subtype sup sub, Functor f) => (sup -> f sup) -> sub -> f sub instance {-# OVERLAPPING #-} Subtype a Void where super = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d super @Int -- super @Int -- :: (Subtype Int sub, Functor f) => (Int -> f Int) -> sub -> f sub diff --git a/generic-lens/src/Data/Generics/Product/Typed.hs b/generic-lens/src/Data/Generics/Product/Typed.hs index acf29f2a..969ddf80 100644 --- a/generic-lens/src/Data/Generics/Product/Typed.hs +++ b/generic-lens/src/Data/Generics/Product/Typed.hs @@ -109,10 +109,11 @@ instance {-# OVERLAPPING #-} HasType a a where setTyped a _ = a {-# INLINE setTyped #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d typed -- typed :: (HasType a s, Functor f) => (a -> f a) -> s -> f s -- --- Note that this might not longer be needed given the above 'HasType a a' instance. +-- Note that this might not longer be needed given the 'HasType a a' instance. instance {-# OVERLAPPING #-} HasType a Void where typed = undefined diff --git a/generic-lens/src/Data/Generics/Sum/Constructors.hs b/generic-lens/src/Data/Generics/Sum/Constructors.hs index b0559dce..ff3f8bba 100644 --- a/generic-lens/src/Data/Generics/Sum/Constructors.hs +++ b/generic-lens/src/Data/Generics/Sum/Constructors.hs @@ -129,7 +129,8 @@ instance (Core.Context ctor s t a b, AsConstructor0 ctor s t a b) => AsConstruct _Ctor eta = _Ctor0 @ctor eta {-# INLINE _Ctor #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d _Ctor -- _Ctor -- :: (AsConstructor ctor s t a b, Choice p, Applicative f) => diff --git a/generic-lens/src/Data/Generics/Sum/Subtype.hs b/generic-lens/src/Data/Generics/Sum/Subtype.hs index cf455808..2a9af4a8 100644 --- a/generic-lens/src/Data/Generics/Sum/Subtype.hs +++ b/generic-lens/src/Data/Generics/Sum/Subtype.hs @@ -109,22 +109,25 @@ instance Core.Context sub sup => AsSubtype sub sup where {-# INLINE _Sub #-} -- | Reflexive case +-- -- >>> _Sub # dog :: Animal -- Dog (MkDog {name = "Shep", age = 3}) instance {-# OVERLAPPING #-} AsSubtype a a where _Sub = id {-# INLINE _Sub #-} --- | See Note [Uncluttering type signatures] ---_Sub --- :: (AsSubtype sub sup, Data.Profunctor.Choice.Choice p, --- Applicative f) => --- p sub (f sub) -> p sup (f sup) +-- | Uncluttering type signatures (see 'Void') +-- +-- >>> :t +d _Sub +-- _Sub +-- :: (AsSubtype sub sup, Choice p, Applicative f) => +-- p sub (f sub) -> p sup (f sup) instance {-# OVERLAPPING #-} AsSubtype a Void where injectSub = undefined projectSub = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d _Sub @Int -- _Sub @Int -- :: (AsSubtype Int sup, Choice p, Applicative f) => diff --git a/generic-lens/src/Data/Generics/Sum/Typed.hs b/generic-lens/src/Data/Generics/Sum/Typed.hs index ffa0e00f..54f37eba 100644 --- a/generic-lens/src/Data/Generics/Sum/Typed.hs +++ b/generic-lens/src/Data/Generics/Sum/Typed.hs @@ -101,7 +101,8 @@ instance Core.Context a s => AsType a s where _Typed eta = prism2prismvl Core.derived eta {-# INLINE _Typed #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d _Typed -- _Typed -- :: (AsType a s, Choice p, Applicative f) => p a (f a) -> p s (f s) @@ -110,7 +111,8 @@ instance {-# OVERLAPPING #-} AsType a Void where injectTyped = undefined projectTyped = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t +d _Typed @Int -- _Typed @Int -- :: (AsType Int s, Choice p, Applicative f) => diff --git a/generic-optics/src/Data/Generics/Product/Fields.hs b/generic-optics/src/Data/Generics/Product/Fields.hs index 6651567f..4c6db393 100644 --- a/generic-optics/src/Data/Generics/Product/Fields.hs +++ b/generic-optics/src/Data/Generics/Product/Fields.hs @@ -155,7 +155,8 @@ instance (Core.Context field s t a b , HasField0 field s t a b) => HasField fiel -- instance {-# OVERLAPPING #-} HasField' field s a => HasField field s s a a where -- field f s = field' @field f s --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t field -- field :: HasField field s t a b => Lens s t a b instance {-# OVERLAPPING #-} HasField f (Void1 a) (Void1 b) a b where diff --git a/generic-optics/src/Data/Generics/Product/Positions.hs b/generic-optics/src/Data/Generics/Product/Positions.hs index 6b6c596b..164c421e 100644 --- a/generic-optics/src/Data/Generics/Product/Positions.hs +++ b/generic-optics/src/Data/Generics/Product/Positions.hs @@ -126,7 +126,8 @@ instance (Core.Context i s t a b , HasPosition0 i s t a b) => HasPosition i s t position = position0 @i {-# INLINE position #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t position -- position :: HasPosition i s t a b => Lens s t a b instance {-# OVERLAPPING #-} HasPosition f (Void1 a) (Void1 b) a b where diff --git a/generic-optics/src/Data/Generics/Product/Subtype.hs b/generic-optics/src/Data/Generics/Product/Subtype.hs index 0c735470..770afd44 100644 --- a/generic-optics/src/Data/Generics/Product/Subtype.hs +++ b/generic-optics/src/Data/Generics/Product/Subtype.hs @@ -118,13 +118,15 @@ instance Core.Context a b => Subtype b a where instance {-# OVERLAPPING #-} Subtype a a where super = Optic id --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t super -- super :: Subtype sup sub => Lens sub sub sup sup instance {-# OVERLAPPING #-} Subtype a Void where super = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t super @Int -- super @Int :: Subtype Int sub => Lens sub sub Int Int instance {-# OVERLAPPING #-} Subtype Void a where diff --git a/generic-optics/src/Data/Generics/Product/Typed.hs b/generic-optics/src/Data/Generics/Product/Typed.hs index 43dfbedf..3b3f5a9a 100644 --- a/generic-optics/src/Data/Generics/Product/Typed.hs +++ b/generic-optics/src/Data/Generics/Product/Typed.hs @@ -110,10 +110,11 @@ instance {-# OVERLAPPING #-} HasType a a where setTyped a _ = a {-# INLINE setTyped #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t typed -- typed :: HasType a s => Lens s s a a -- --- Note that this might not longer be needed given the above 'HasType a a' instance. +-- Note that this might not longer be needed given the 'HasType a a' instance. instance {-# OVERLAPPING #-} HasType a Void where typed = undefined diff --git a/generic-optics/src/Data/Generics/Sum/Constructors.hs b/generic-optics/src/Data/Generics/Sum/Constructors.hs index f5ec2c73..cce9a07c 100644 --- a/generic-optics/src/Data/Generics/Sum/Constructors.hs +++ b/generic-optics/src/Data/Generics/Sum/Constructors.hs @@ -128,7 +128,8 @@ instance (Core.Context ctor s t a b, AsConstructor0 ctor s t a b) => AsConstruct _Ctor = _Ctor0 @ctor {-# INLINE _Ctor #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t _Ctor -- _Ctor :: AsConstructor ctor s t a b => Prism s t a b instance {-# OVERLAPPING #-} AsConstructor ctor (Void1 a) (Void1 b) a b where diff --git a/generic-optics/src/Data/Generics/Sum/Subtype.hs b/generic-optics/src/Data/Generics/Sum/Subtype.hs index ee1c2f0d..bb676e21 100644 --- a/generic-optics/src/Data/Generics/Sum/Subtype.hs +++ b/generic-optics/src/Data/Generics/Sum/Subtype.hs @@ -115,16 +115,16 @@ instance {-# OVERLAPPING #-} AsSubtype a a where _Sub = Optic id {-# INLINE _Sub #-} --- | See Note [Uncluttering type signatures] ---_Sub --- :: (AsSubtype sub sup, Data.Profunctor.Choice.Choice p, --- Applicative f) => --- p sub (f sub) -> p sup (f sup) +-- | Uncluttering type signatures (see 'Void') +-- +-- >>> :t _Sub +--_Sub :: AsSubtype sub sup => Prism' sup sub instance {-# OVERLAPPING #-} AsSubtype a Void where injectSub = undefined projectSub = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t _Sub @Int -- _Sub @Int :: AsSubtype Int sup => Prism' sup Int instance {-# OVERLAPPING #-} AsSubtype Void a where diff --git a/generic-optics/src/Data/Generics/Sum/Typed.hs b/generic-optics/src/Data/Generics/Sum/Typed.hs index 2a4e7b17..56db6a4d 100644 --- a/generic-optics/src/Data/Generics/Sum/Typed.hs +++ b/generic-optics/src/Data/Generics/Sum/Typed.hs @@ -101,7 +101,8 @@ instance Core.Context a s => AsType a s where _Typed = normalisePrism (Optic Core.derived) {-# INLINE _Typed #-} --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t _Typed -- _Typed :: AsType a s => Prism' s a instance {-# OVERLAPPING #-} AsType a Void where @@ -109,7 +110,8 @@ instance {-# OVERLAPPING #-} AsType a Void where injectTyped = undefined projectTyped = undefined --- | See Note [Uncluttering type signatures] +-- | Uncluttering type signatures (see 'Void') +-- -- >>> :t _Typed @Int -- _Typed @Int :: AsType Int s => Prism' s Int instance {-# OVERLAPPING #-} AsType Void a where