{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE UndecidableInstances #-} module Encode where import Data.Coerce import Data.List import Data.Override.Internal import GHC.Generics class Encode a where encode :: a -> String default encode :: (Generic a, GEncode (Rep a)) => a -> String encode = gencode . from instance ( Generic a , GOverride xs (Rep a) , GEncode (Rep (Override a xs)) ) => Encode (Override a xs) instance ( u ~ Using ms a xs , Coercible a u , Encode u ) => Encode (Overridden ms a xs) where encode = encode @u . coerce class GEncode f where gencode :: f a -> String instance (GEncode f) => GEncode (M1 D x f) where gencode (M1 f) = gencode f instance (GEncode f, Constructor c) => GEncode (M1 C c f) where gencode m@(M1 f) = conName m <> ":" <> gencode f instance (GEncode f, GEncode g) => GEncode (f :*: g) where gencode (f :*: g) = gencode f <> "," <> gencode g instance (GEncode f, GEncode g) => GEncode (f :+: g) where gencode = \case L1 f -> gencode f R1 g -> gencode g instance (GEncode f, Selector s) => GEncode (M1 S s f) where gencode m@(M1 f) = if null (selName m) then gencode f else selName m <> "=" <> gencode f instance (Encode a) => GEncode (K1 R a) where gencode (K1 a) = encode a instance GEncode U1 where gencode _ = "" instance Encode Int where encode = show instance Encode Char where encode = pure instance {-# OVERLAPPING #-} Encode String where encode = id instance (Encode a) => Encode [a] where encode = intercalate "," . map encode newtype ListOf a = ListOf { unListOf :: [a] } instance (Encode a) => Encode (ListOf a) where encode = intercalate "," . map encode . unListOf