{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Sv.Encode.Type (
Encode (Encode, getEncode)
, NameEncode (..)
) where
import Control.Applicative (liftA2)
import Control.Monad.Writer (Writer)
import Data.Bifoldable (bifoldMap)
import Data.ByteString.Builder (Builder)
import Data.Functor.Contravariant (Contravariant (contramap))
import Data.Functor.Contravariant.Compose (ComposeFC (ComposeFC))
import Data.Functor.Contravariant.Divisible (Divisible (divide, conquer), Decidable (choose, lose))
import Data.Semigroup (Semigroup ((<>)))
import Data.Sequence (Seq)
import Data.Void (absurd)
import Data.Sv.Encode.Options
newtype Encode a =
Encode { getEncode :: EncodeOptions -> a -> Seq Builder }
deriving (Semigroup, Monoid)
instance Contravariant Encode where
contramap f (Encode g) = Encode $ fmap (. f) g
instance Divisible Encode where
conquer = Encode mempty
divide f (Encode x) (Encode y) =
Encode $ \e a -> bifoldMap (x e) (y e) (f a)
instance Decidable Encode where
lose f = Encode (const (absurd . f))
choose f (Encode x) (Encode y) =
Encode $ \e a -> either (x e) (y e) (f a)
newtype NameEncode a =
NameEncode { unNamedE :: ComposeFC (Writer (Seq Builder)) Encode a}
deriving (Contravariant, Divisible)
instance Semigroup (NameEncode a) where
NameEncode (ComposeFC a) <> NameEncode (ComposeFC b) =
NameEncode (ComposeFC (liftA2 (<>) a b))
instance Monoid (NameEncode a) where
mappend = (<>)
mempty = NameEncode (ComposeFC (pure mempty))