{-# LANGUAGE PackageImports #-} {-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE UndecidableInstances #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Generics.Sum.Any -- Copyright : (C) 2020 Csongor Kiss -- License : BSD3 -- Maintainer : Csongor Kiss <kiss.csongor.kiss@gmail.com> -- Stability : experimental -- Portability : non-portable -- -- Derive a variety of prisms generically. -- ----------------------------------------------------------------------------- module Data.Generics.Sum.Any ( -- *Prisms -- -- $setup AsAny (..) ) where import "this" Data.Generics.Internal.VL.Prism import "this" Data.Generics.Sum.Constructors import "this" Data.Generics.Sum.Typed -- $setup -- == /Running example:/ -- -- >>> :set -XTypeApplications -- >>> :set -XDataKinds -- >>> :set -XDeriveGeneric -- >>> import GHC.Generics -- >>> import Control.Lens -- >>> :{ -- data Animal -- = Dog Dog -- | Cat Name Age -- | Duck Age -- deriving (Generic, Show) -- data Dog -- = MkDog -- { name :: Name -- , age :: Age -- } -- deriving (Generic, Show) -- type Name = String -- type Age = Int -- dog, cat, duck :: Animal -- dog = Dog (MkDog "Shep" 3) -- cat = Cat "Mog" 5 -- duck = Duck 2 -- :} -- |Sums that have generic prisms. class AsAny sel a s | s sel -> a where -- |A prism that projects a sum as identified by some selector. Currently -- supported selectors are constructor names and unique types. Compatible -- with the lens package's 'Control.Lens.Prism' type. -- -- >>> dog ^? _As @"Dog" -- Just (MkDog {name = "Shep", age = 3}) -- -- >>> dog ^? _As @Dog -- Just (MkDog {name = "Shep", age = 3}) -- -- >>> dog ^? _As @"Cat" -- Nothing -- -- >>> cat ^? _As @(Name, Age) -- Just ("Mog",5) -- -- >>> cat ^? _As @"Cat" -- Just ("Mog",5) -- -- >>> _As @"Cat" # ("Garfield", 6) :: Animal -- Cat "Garfield" 6 -- -- >>> duck ^? _As @Age -- Just 2 _As :: Prism s s a a instance AsConstructor ctor s s a a => AsAny ctor a s where _As :: Prism s s a a _As = forall (ctor :: Symbol) s t a b. AsConstructor ctor s t a b => Prism s t a b _Ctor @ctor instance AsType a s => AsAny a a s where _As :: Prism s s a a _As = forall a s. AsType a s => Prism s s a a _Typed @a