module Data.Extensible.Plain (
K0(..)
, _K0
, AllOf
, OneOf
, (<%)
, pluck
, bury
, (<%|)
, accessing
, decFields
, decFieldsDeriving
) where
import Data.Extensible.Internal
import Data.Extensible.Internal.Rig
import Data.Extensible.Class
import Data.Extensible.Product
import Data.Extensible.Sum
import Unsafe.Coerce
import Language.Haskell.TH hiding (Match(..))
import Data.Char
import Data.Coerce
type AllOf xs = K0 :* xs
type OneOf xs = K0 :| xs
(<%) :: x -> AllOf xs -> AllOf (x ': xs)
(<%) = unsafeCoerce (<:*)
infixr 5 <%
pluck :: (x ∈ xs) => AllOf xs -> x
pluck = views piece getK0
bury :: (x ∈ xs) => x -> OneOf xs
bury = embed . K0
(<%|) :: (x -> r) -> (OneOf xs -> r) -> OneOf (x ': xs) -> r
(<%|) = unsafeCoerce (<:|)
infixr 1 <%|
accessing :: (Coercible b a, b ∈ xs) => (a -> b) -> Lens' (AllOf xs) a
accessing c f = piece (_K0 (fmap c . f . coerce))
decFields :: DecsQ -> DecsQ
decFields = decFieldsDeriving []
decFieldsDeriving :: [Name] -> DecsQ -> DecsQ
decFieldsDeriving drv' ds = ds >>= fmap concat . mapM mkBody
where
mkBody (NewtypeD cx name_ tvs (NormalC nc [(st, ty)]) drv) = do
let name = let (x:xs) = nameBase name_ in mkName (toLower x : xs)
xs <- newName "xs"
sequence [return $ NewtypeD cx name_ tvs (NormalC nc [(st, ty)]) (drv' ++ drv)
,sigD name
#if MIN_VERSION_template_haskell(2,10,0)
$ forallT (PlainTV xs : tvs) (sequence [conT ''Member `appT` varT xs `appT` conT name_])
#else
$ forallT (PlainTV xs : tvs) (sequence [classP ''Member [varT xs, conT name_]])
#endif
$ conT ''Lens' `appT` (conT ''AllOf `appT` varT xs) `appT` return ty
, valD (varP name) (normalB $ varE 'accessing `appE` conE nc) []
, return $ PragmaD $ InlineP name Inline FunLike AllPhases
]
mkBody (TySynD name_ tvs ty) = mkBody (NewtypeD [] name_ tvs (NormalC (mkName (nameBase name_)) [(NotStrict, ty)]) [])
mkBody _ = fail "Unsupported declaration: genField handles newtype declarations or type synonyms"