-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Spec based JSON parsing/serialisation
--   
--   Low boilerplate, easy to use and very fast JSON serialisation and
--   parsing without generics or TemplateHaskell
@package highjson
@version 0.4.0.0

module Data.HighJson
data HighSpec a (ty :: SpecType) as
HighSpec :: !Text -> !(Maybe Text) -> !(BodySpec ty a as) -> HighSpec a as
[hs_name] :: HighSpec a as -> !Text
[hs_description] :: HighSpec a as -> !(Maybe Text)
[hs_bodySpec] :: HighSpec a as -> !(BodySpec ty a as)
data SpecType
SpecRecord :: SpecType
SpecSum :: SpecType
SpecEnum :: SpecType

-- | The specification for a record. Contains a name, an optional
--   description, the constructor and a description how to parse and
--   serialize fields respecting a given json key.
recSpec :: (IsDataSpec q, DContainer q ~ RecordFields) => Text -> Maybe Text -> HVectElim (DFields q) (DType q) -> q -> RecordTypeSpec (DType q) (DFields q)

-- | A specification for a record
type RecordTypeSpec t flds = HighSpec t  'SpecRecord flds

-- | A required json field. The key must be present in the json.
reqField :: FromJSON f => Text -> (t -> f) -> RecordField t f

-- | Alias for <a>reqField</a>
(.=) :: FromJSON f => Text -> (t -> f) -> RecordField t f

-- | An optional json field.
optField :: FromJSON f => Text -> (t -> Maybe f) -> RecordField t (Maybe f)

-- | Alias for <a>optField</a>
(.=?) :: FromJSON f => Text -> (t -> Maybe f) -> RecordField t (Maybe f)

-- | The specification for a sum type. Contains a name, an optional
--   description and a mapping from all constructor (prims) to their
--   respective json fields
sumSpec :: (IsDataSpec q, DContainer q ~ SumOptions) => Text -> Maybe Text -> q -> SumTypeSpec (DType q) (DFields q)

-- | A specification for an arbitrary sum type
type SumTypeSpec t flds = HighSpec t  'SpecSum flds

-- | An option of a sum type
sumOpt :: Text -> Prism' t o -> SumOption t o

-- | Alias for <a>sumOpt</a>
(.->) :: Text -> Prism' t o -> SumOption t o

-- | The specification for a classic enum type. Contains a name, an
--   optional description and a mapping from all constructors to ther
--   counterpart json string names.
enumSpec :: (IsDataSpec q, DContainer q ~ PhantomEnumContainer) => Text -> Maybe Text -> q -> EnumTypeSpec (DType q) (DFields q)

-- | A specification for a classic enum
type EnumTypeSpec t flds = HighSpec t  'SpecEnum flds

-- | An option of a classic enum
enumOpt :: Text -> Prism' t () -> EnumOption t

-- | Alias for <a>enumOpt</a>
(@->) :: Text -> Prism' t () -> EnumOption t

-- | A type class that allows a unified notation for records and sum types.
--   Build specifications using '(:&amp;)' and '(.=)', '(.=?)', '(.-&gt;)'
--   or '(@-&gt;)'
class IsDataSpec t where {
    type family DFields t :: [*];
    type family DType t;
    type family DContainer t :: * -> [*] -> *;
}
compileRec :: IsDataSpec t => t -> (DContainer t) (DType t) (DFields t)

-- | Combination of two local specifications. For records, these are
--   fields, for sum types and enums these are the options.
data a (:&) b
(:&) :: a -> b -> (:&) a b
jsonSerializer :: AllHave ToJSON as => HighSpec a ty as -> a -> Value
jsonEncoder :: AllHave ToJSON as => HighSpec a ty as -> a -> Encoding
jsonParser :: AllHave FromJSON as => HighSpec a ty as -> Value -> Parser a
data BodySpec ty a as
[BodySpecRecord] :: !(RecordSpec a as) -> BodySpec  'SpecRecord a as
[BodySpecSum] :: !(SumSpec a as) -> BodySpec  'SpecSum a as
[BodySpecEnum] :: !(EnumSpec a) -> BodySpec  'SpecEnum a as
data RecordField t f
RecordField :: !Text -> !Bool -> (Object -> Text -> Parser f) -> !(t -> f) -> RecordField t f
[rf_jsonKey] :: RecordField t f -> !Text
[rf_optional] :: RecordField t f -> !Bool
[rf_jsonLoader] :: RecordField t f -> Object -> Text -> Parser f
[rf_get] :: RecordField t f -> !(t -> f)
data RecordSpec a fs
RecordSpec :: (HVect fs -> a) -> RecordFields a fs -> RecordSpec a fs
[rs_make] :: RecordSpec a fs -> HVect fs -> a
[rs_fields] :: RecordSpec a fs -> RecordFields a fs
data RecordFields t fs
[RFEmpty] :: RecordFields t '[]
[:+:] :: RecordField t f -> RecordFields t fs -> RecordFields t (f : fs)
data SumOption t o
SumOption :: !Text -> !(Prism' t o) -> SumOption t o
[so_jsonKey] :: SumOption t o -> !Text
[so_prism] :: SumOption t o -> !(Prism' t o)
data SumSpec a os
SumSpec :: SumOptions a os -> SumSpec a os
[ss_options] :: SumSpec a os -> SumOptions a os
data SumOptions t os
[SOEmpty] :: SumOptions t '[]
[:|:] :: SumOption t o -> SumOptions t os -> SumOptions t (o : os)
data EnumOption t
EnumOption :: !Text -> !(Prism' t ()) -> EnumOption t
[eo_jsonKey] :: EnumOption t -> !Text
[eo_prism] :: EnumOption t -> !(Prism' t ())
data EnumSpec a
EnumSpec :: [EnumOption a] -> EnumSpec a
[es_options] :: EnumSpec a -> [EnumOption a]

-- | A type that can be converted to JSON.
--   
--   Instances in general <i>must</i> specify <a>toJSON</a> and
--   <i>should</i> (but don't need to) specify <a>toEncoding</a>.
--   
--   An example type and instance:
--   
--   <pre>
--   -- Allow ourselves to write <a>Text</a> literals.
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   data Coord = Coord { x :: Double, y :: Double }
--   
--   instance <a>ToJSON</a> Coord where
--     <a>toJSON</a> (Coord x y) = <a>object</a> ["x" <a>.=</a> x, "y" <a>.=</a> y]
--   
--     <a>toEncoding</a> (Coord x y) = <tt>pairs</tt> ("x" <a>.=</a> x <a>&lt;&gt;</a> "y" <a>.=</a> y)
--   </pre>
--   
--   Instead of manually writing your <a>ToJSON</a> instance, there are two
--   options to do it automatically:
--   
--   <ul>
--   <li><a>Data.Aeson.TH</a> provides Template Haskell functions which
--   will derive an instance at compile time. The generated instance is
--   optimized for your type so it will probably be more efficient than the
--   following option.</li>
--   <li>The compiler can provide a default generic implementation for
--   <a>toJSON</a>.</li>
--   </ul>
--   
--   To use the second, simply add a <tt>deriving <a>Generic</a></tt>
--   clause to your datatype and declare a <a>ToJSON</a> instance. If you
--   require nothing other than <a>defaultOptions</a>, it is sufficient to
--   write (and this is the only alternative where the default
--   <a>toJSON</a> implementation is sufficient):
--   
--   <pre>
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import <a>GHC.Generics</a>
--   
--   data Coord = Coord { x :: Double, y :: Double } deriving <a>Generic</a>
--   
--   instance <a>ToJSON</a> Coord where
--       <a>toEncoding</a> = <a>genericToEncoding</a> <a>defaultOptions</a>
--   </pre>
--   
--   If on the other hand you wish to customize the generic decoding, you
--   have to implement both methods:
--   
--   <pre>
--   customOptions = <a>defaultOptions</a>
--                   { <a>fieldLabelModifier</a> = <a>map</a> <a>toUpper</a>
--                   }
--   
--   instance <a>ToJSON</a> Coord where
--       <a>toJSON</a>     = <a>genericToJSON</a> customOptions
--       <a>toEncoding</a> = <a>genericToEncoding</a> customOptions
--   </pre>
--   
--   Previous versions of this library only had the <a>toJSON</a> method.
--   Adding <a>toEncoding</a> had to reasons:
--   
--   <ol>
--   <li>toEncoding is more efficient for the common case that the output
--   of <a>toJSON</a> is directly serialized to a <tt>ByteString</tt>.
--   Further, expressing either method in terms of the other would be
--   non-optimal.</li>
--   <li>The choice of defaults allows a smooth transition for existing
--   users: Existing instances that do not define <a>toEncoding</a> still
--   compile and have the correct semantics. This is ensured by making the
--   default implementation of <a>toEncoding</a> use <a>toJSON</a>. This
--   produces correct results, but since it performs an intermediate
--   conversion to a <a>Value</a>, it will be less efficient than directly
--   emitting an <a>Encoding</a>. (this also means that specifying nothing
--   more than <tt>instance ToJSON Coord</tt> would be sufficient as a
--   generically decoding instance, but there probably exists no good
--   reason to not specify <a>toEncoding</a> in new instances.)</li>
--   </ol>
class ToJSON a

-- | Convert a Haskell value to a JSON-friendly intermediate type.
toJSON :: ToJSON a => a -> Value

-- | Encode a Haskell value as JSON.
--   
--   The default implementation of this method creates an intermediate
--   <a>Value</a> using <a>toJSON</a>. This provides source-level
--   compatibility for people upgrading from older versions of this
--   library, but obviously offers no performance advantage.
--   
--   To benefit from direct encoding, you <i>must</i> provide an
--   implementation for this method. The easiest way to do so is by having
--   your types implement <a>Generic</a> using the <tt>DeriveGeneric</tt>
--   extension, and then have GHC generate a method body as follows.
--   
--   <pre>
--   instance <a>ToJSON</a> Coord where
--       <a>toEncoding</a> = <a>genericToEncoding</a> <a>defaultOptions</a>
--   </pre>
toEncoding :: ToJSON a => a -> Encoding
toJSONList :: ToJSON a => [a] -> Value
toEncodingList :: ToJSON a => [a] -> Encoding

-- | A type that can be converted from JSON, with the possibility of
--   failure.
--   
--   In many cases, you can get the compiler to generate parsing code for
--   you (see below). To begin, let's cover writing an instance by hand.
--   
--   There are various reasons a conversion could fail. For example, an
--   <a>Object</a> could be missing a required key, an <a>Array</a> could
--   be of the wrong size, or a value could be of an incompatible type.
--   
--   The basic ways to signal a failed conversion are as follows:
--   
--   <ul>
--   <li><tt>empty</tt> and <tt>mzero</tt> work, but are terse and
--   uninformative;</li>
--   <li><a>fail</a> yields a custom error message;</li>
--   <li><a>typeMismatch</a> produces an informative message for cases when
--   the value encountered is not of the expected type.</li>
--   </ul>
--   
--   An example type and instance using <a>typeMismatch</a>:
--   
--   <pre>
--   -- Allow ourselves to write <a>Text</a> literals.
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   data Coord = Coord { x :: Double, y :: Double }
--   
--   instance <a>FromJSON</a> Coord where
--       <a>parseJSON</a> (<a>Object</a> v) = Coord
--           <a>&lt;$&gt;</a> v <a>.:</a> "x"
--           <a>&lt;*&gt;</a> v <a>.:</a> "y"
--   
--       -- We do not expect a non-<a>Object</a> value here.
--       -- We could use <tt>mzero</tt> to fail, but <a>typeMismatch</a>
--       -- gives a much more informative error message.
--       <a>parseJSON</a> invalid    = <a>typeMismatch</a> "Coord" invalid
--   </pre>
--   
--   For this common case of only being concerned with a single type of
--   JSON value, the functions <a>withObject</a>, <a>withNumber</a>, etc.
--   are provided. Their use is to be preferred when possible, since they
--   are more terse. Using <a>withObject</a>, we can rewrite the above
--   instance (assuming the same language extension and data type) as:
--   
--   <pre>
--   instance <a>FromJSON</a> Coord where
--       <a>parseJSON</a> = <a>withObject</a> "Coord" $ \v -&gt; Coord
--           <a>&lt;$&gt;</a> v <a>.:</a> "x"
--           <a>&lt;*&gt;</a> v <a>.:</a> "y"
--   </pre>
--   
--   Instead of manually writing your <a>FromJSON</a> instance, there are
--   two options to do it automatically:
--   
--   <ul>
--   <li><a>Data.Aeson.TH</a> provides Template Haskell functions which
--   will derive an instance at compile time. The generated instance is
--   optimized for your type so it will probably be more efficient than the
--   following option.</li>
--   <li>The compiler can provide a default generic implementation for
--   <a>parseJSON</a>.</li>
--   </ul>
--   
--   To use the second, simply add a <tt>deriving <a>Generic</a></tt>
--   clause to your datatype and declare a <a>FromJSON</a> instance for
--   your datatype without giving a definition for <a>parseJSON</a>.
--   
--   For example, the previous example can be simplified to just:
--   
--   <pre>
--   {-# LANGUAGE DeriveGeneric #-}
--   
--   import <a>GHC.Generics</a>
--   
--   data Coord = Coord { x :: Double, y :: Double } deriving <a>Generic</a>
--   
--   instance <a>FromJSON</a> Coord
--   </pre>
--   
--   The default implementation will be equivalent to <tt>parseJSON =
--   <a>genericParseJSON</a> <a>defaultOptions</a></tt>; If you need
--   different options, you can customize the generic decoding by defining:
--   
--   <pre>
--   customOptions = <a>defaultOptions</a>
--                   { <a>fieldLabelModifier</a> = <a>map</a> <a>toUpper</a>
--                   }
--   
--   instance <a>FromJSON</a> Coord where
--       <a>parseJSON</a> = <a>genericParseJSON</a> customOptions
--   </pre>
class FromJSON a
parseJSON :: FromJSON a => Value -> Parser a
parseJSONList :: FromJSON a => Value -> Parser [a]
newtype PhantomEnumContainer t (ts :: [*])
PhantomEnumContainer :: [EnumOption t] -> PhantomEnumContainer t
[unPhantomEnumContainer] :: PhantomEnumContainer t -> [EnumOption t]

-- | A monoidal type class that respects type level lists associated to the
--   bodies
class CombinableContainer t
combineContainer :: CombinableContainer t => t a (as :: [*]) -> t a (bs :: [*]) -> t a (Append as bs)
instance (GHC.Enum.Bounded b, GHC.Enum.Bounded a) => GHC.Enum.Bounded (a Data.HighJson.:& b)
instance Data.Foldable.Foldable ((Data.HighJson.:&) a)
instance Data.Traversable.Traversable ((Data.HighJson.:&) a)
instance GHC.Base.Functor ((Data.HighJson.:&) a)
instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (a Data.HighJson.:& b)
instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (a Data.HighJson.:& b)
instance Data.HighJson.CombinableContainer Data.HighJson.PhantomEnumContainer
instance Data.HighJson.IsDataSpec (Data.HighJson.Types.EnumOption t)
instance Data.HighJson.IsDataSpec (Data.HighJson.Types.RecordField t f)
instance Data.HighJson.IsDataSpec (Data.HighJson.Types.SumOption t f)
instance (Data.HighJson.IsDataSpec x, Data.HighJson.IsDataSpec y, Data.HighJson.DType x ~ Data.HighJson.DType y, Data.HighJson.DContainer x ~ Data.HighJson.DContainer y, Data.HighJson.CombinableContainer (Data.HighJson.DContainer x)) => Data.HighJson.IsDataSpec (x Data.HighJson.:& y)
instance Data.HighJson.CombinableContainer Data.HighJson.Types.RecordFields
instance Data.HighJson.CombinableContainer Data.HighJson.Types.SumOptions
instance (GHC.Base.Monoid a, GHC.Base.Monoid b) => GHC.Base.Monoid (a Data.HighJson.:& b)
