{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Binary.Tagged
(
BinaryTagged(..),
BinaryTagged',
binaryTag,
binaryTag',
binaryUntag,
binaryUntag',
StructuralInfo(..),
taggedEncode,
taggedDecode,
taggedDecodeOrFail,
taggedEncodeFile,
taggedDecodeFile,
taggedDecodeFileOrFail,
HasStructuralInfo(..),
HasSemanticVersion(..),
Version,
Interleave,
SumUpTo,
Div2,
ghcStructuralInfo,
ghcNominalType,
ghcStructuralInfo1,
sopStructuralInfo,
sopNominalType,
sopStructuralInfo1,
sopStructuralInfoS,
sopNominalTypeS,
sopStructuralInfo1S,
structuralInfoSha1Digest,
structuralInfoSha1ByteStringDigest,
) where
import Control.Applicative
import Control.Monad
import Data.Binary
import Data.Binary.Get (ByteOffset)
import Data.ByteString as BS
import Data.ByteString.Lazy as LBS
import Data.Digest.Pure.SHA
import Data.Monoid ((<>))
import Data.Proxy
import Generics.SOP as SOP
import Generics.SOP.GGP as SOP
#if MIN_VERSION_generics_sop(0,2,0)
import Generics.SOP.Constraint as SOP
#endif
#if !MIN_VERSION_base(4,8,0)
import Data.Foldable (Foldable)
import Data.Traversable (Traversable)
#endif
import qualified GHC.Generics as GHC
import GHC.TypeLits
import Data.Int
import qualified Data.Aeson as Aeson
import qualified Data.Array.IArray as Array
import qualified Data.Array.Unboxed as Array
import qualified Data.Fixed as Fixed
import qualified Data.HashMap.Lazy as HML
import qualified Data.HashSet as HS
import qualified Data.IntMap as IntMap
import qualified Data.IntSet as IntSet
import qualified Data.Map as Map
import qualified Data.Monoid as Monoid
import qualified Data.Ratio as Ratio
import qualified Data.Sequence as Seq
import qualified Data.Set as Set
import qualified Data.Text as S
import qualified Data.Text.Lazy as L
import qualified Data.Time as Time
import qualified Data.Vector as V
import qualified Data.Vector.Storable as S
import qualified Data.Vector.Unboxed as U
import qualified Data.Version as Version
newtype BinaryTagged (v :: k) a = BinaryTagged { unBinaryTagged :: a }
deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable, GHC.Generic, GHC.Generic1)
type BinaryTagged' a = BinaryTagged (SemanticVersion a) a
binaryTag :: Proxy v -> a -> BinaryTagged v a
binaryTag _ = BinaryTagged
binaryTag' :: HasSemanticVersion a => a -> BinaryTagged' a
binaryTag' = BinaryTagged
binaryUntag :: Proxy v -> BinaryTagged v a -> a
binaryUntag _ = unBinaryTagged
binaryUntag' :: HasSemanticVersion a => BinaryTagged' a -> a
binaryUntag' = unBinaryTagged
taggedEncode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => a -> LBS.ByteString
taggedEncode = encode . binaryTag (Proxy :: Proxy (SemanticVersion a))
taggedDecode :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => LBS.ByteString -> a
taggedDecode = binaryUntag (Proxy :: Proxy (SemanticVersion a)) . decode
taggedDecodeOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a)
=> LBS.ByteString
-> Either (LBS.ByteString, ByteOffset, String) (LBS.ByteString, ByteOffset, a)
taggedDecodeOrFail = fmap3 (binaryUntag (Proxy :: Proxy (SemanticVersion a))) . decodeOrFail
where fmap3 f = fmap (\(a, b, c) -> (a, b, f c))
taggedEncodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> a -> IO ()
taggedEncodeFile filepath = encodeFile filepath . binaryTag (Proxy :: Proxy (SemanticVersion a))
taggedDecodeFile :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO a
taggedDecodeFile = fmap (binaryUntag (Proxy :: Proxy (SemanticVersion a))) . decodeFile
taggedDecodeFileOrFail :: forall a. (HasStructuralInfo a, HasSemanticVersion a, Binary a) => FilePath -> IO (Either (ByteOffset, String) a)
taggedDecodeFileOrFail = (fmap . fmap) (binaryUntag (Proxy :: Proxy (SemanticVersion a))) . decodeFileOrFail
instance Applicative (BinaryTagged v) where
pure = return
(<*>) = ap
instance Monad (BinaryTagged v) where
return = BinaryTagged
BinaryTagged m >>= k = k m
instance Monoid.Monoid a => Monoid.Monoid (BinaryTagged v a) where
mempty = pure Monoid.mempty
mappend = liftA2 Monoid.mappend
type Version = Word32
instance (Binary a, HasStructuralInfo a, KnownNat v) => Binary (BinaryTagged v a) where
put (BinaryTagged x) = put ver' >> put hash' >> put x
where
proxyV = Proxy :: Proxy v
proxyA = Proxy :: Proxy a
ver' = fromIntegral (natVal proxyV) :: Version
hash' = structuralInfoSha1ByteStringDigest . structuralInfo $ proxyA
get = do
ver <- get
if ver == ver'
then do hash <- get
if hash == hash'
then fmap BinaryTagged get
else fail $ "Non matching structure hashes: got" <> show hash <> "; expected: " <> show hash'
else fail $ "Non matching versions: got " <> show ver <> "; expected: " <> show ver'
where
proxyV = Proxy :: Proxy v
proxyA = Proxy :: Proxy a
ver' = fromIntegral (natVal proxyV) :: Version
hash' = bytestringDigest . structuralInfoSha1Digest . structuralInfo $ proxyA
data StructuralInfo = NominalType String
| NominalNewtype String StructuralInfo
| StructuralInfo String [[StructuralInfo]]
deriving (Eq, Ord, Show, GHC.Generic)
instance Binary StructuralInfo
class HasStructuralInfo a where
structuralInfo :: Proxy a -> StructuralInfo
default structuralInfo :: ( GHC.Generic a
, All2 HasStructuralInfo (GCode a)
, GDatatypeInfo a
#if MIN_VERSION_generics_sop(0,2,0)
, SListI2 (GCode a)
#else
, SingI (GCode a)
#endif
) => Proxy a -> StructuralInfo
structuralInfo = ghcStructuralInfo
class KnownNat (SemanticVersion a) => HasSemanticVersion (a :: *) where
type SemanticVersion a :: Nat
type SemanticVersion a = 0
instance HasStructuralInfo StructuralInfo
instance HasSemanticVersion StructuralInfo
structuralInfoSha1Digest :: StructuralInfo -> Digest SHA1State
structuralInfoSha1Digest = sha1 . encode
structuralInfoSha1ByteStringDigest :: StructuralInfo -> LBS.ByteString
structuralInfoSha1ByteStringDigest = bytestringDigest . structuralInfoSha1Digest
ghcStructuralInfo :: ( GHC.Generic a
, All2 HasStructuralInfo (GCode a)
, GDatatypeInfo a
#if MIN_VERSION_generics_sop(0,2,0)
, SListI2 (GCode a)
#else
, SingI (GCode a)
#endif
)
=> Proxy a
-> StructuralInfo
ghcStructuralInfo proxy = sopStructuralInfoS (gdatatypeInfo proxy)
ghcNominalType :: (GHC.Generic a, GDatatypeInfo a) => Proxy a -> StructuralInfo
ghcNominalType proxy = sopNominalTypeS (gdatatypeInfo proxy)
ghcStructuralInfo1 :: forall f a. (GHC.Generic1 f, GDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo
ghcStructuralInfo1 proxy = sopStructuralInfo1S (structuralInfo (Proxy :: Proxy a)) (gdatatypeInfo proxy)
sopStructuralInfo :: forall a. (Generic a, HasDatatypeInfo a, All2 HasStructuralInfo (Code a)) => Proxy a -> StructuralInfo
sopStructuralInfo proxy = sopStructuralInfoS (datatypeInfo proxy)
sopStructuralInfoS :: forall xss. ( All2 HasStructuralInfo xss
#if MIN_VERSION_generics_sop(0,2,0)
, SListI2 xss
#else
, SingI xss
#endif
)
=> DatatypeInfo xss
-> StructuralInfo
sopStructuralInfoS di@(Newtype _ _ ci) = NominalNewtype (datatypeName di) (sopNominalNewtype ci)
sopStructuralInfoS di@(ADT _ _ _) = StructuralInfo (datatypeName di) (sopNominalAdtPOP (hpure Proxy :: POP Proxy xss))
sopNominalNewtype :: forall x. HasStructuralInfo x => ConstructorInfo '[x] -> StructuralInfo
sopNominalNewtype _ = structuralInfo (Proxy :: Proxy x)
sopNominalAdtPOP :: (All2 HasStructuralInfo xss) => POP Proxy xss -> [[StructuralInfo]]
sopNominalAdtPOP (POP np2) = sopNominalAdt np2
sopNominalAdt :: (All2 HasStructuralInfo xss) => NP (NP Proxy) xss -> [[StructuralInfo]]
sopNominalAdt Nil = []
sopNominalAdt (p :* ps) = sopStructuralInfoP p : sopNominalAdt ps
sopStructuralInfoP :: (All HasStructuralInfo xs) => NP Proxy xs -> [StructuralInfo]
sopStructuralInfoP Nil = []
sopStructuralInfoP (proxy :* rest) = structuralInfo proxy : sopStructuralInfoP rest
sopNominalType :: forall a. (Generic a, HasDatatypeInfo a) => Proxy a -> StructuralInfo
sopNominalType proxy = sopNominalTypeS (datatypeInfo proxy)
sopNominalTypeS :: DatatypeInfo xss -> StructuralInfo
sopNominalTypeS di = NominalType (datatypeName di)
sopStructuralInfo1 :: forall f a. (Generic (f a), HasDatatypeInfo (f a), HasStructuralInfo a) => Proxy (f a) -> StructuralInfo
sopStructuralInfo1 proxy = sopStructuralInfo1S (structuralInfo (Proxy :: Proxy a)) (datatypeInfo proxy)
sopStructuralInfo1S :: StructuralInfo -> DatatypeInfo xss -> StructuralInfo
sopStructuralInfo1S nsop di = NominalNewtype (datatypeName di) nsop
-- SOP helpers
datatypeName :: DatatypeInfo xss -> DatatypeName
datatypeName (Newtype _ d _) = d
datatypeName (ADT _ d _) = d
-- | Interleaving
--
-- > 3 | 9 . . . .
-- > 2 | 5 8 . . .
-- > 1 | 2 4 7 11 .
-- > 0 | 0 1 3 6 10
-- > -----------------
-- > 0 1 2 3 4
--
-- This can be calculated by @f x y = sum ([0..x+y]) + y@
type Interleave (n :: Nat) (m :: Nat) = SumUpTo (n + m) + m
type SumUpTo (n :: Nat) = Div2 (n * (n + 1))
type family Div2 (n :: Nat) :: Nat where
Div2 0 = 0
Div2 1 = 0
Div2 n = 1 + Div2 (n - 2)
-- Instances
instance HasStructuralInfo Bool where structuralInfo = ghcNominalType
instance HasStructuralInfo Char where structuralInfo = ghcNominalType
instance HasStructuralInfo Int where structuralInfo = ghcNominalType
instance HasStructuralInfo Word where structuralInfo _ = NominalType "Word"
instance HasStructuralInfo Integer where structuralInfo _ = NominalType "Integer"
instance HasStructuralInfo Int8 where structuralInfo _ = NominalType "Int8"
instance HasStructuralInfo Int16 where structuralInfo _ = NominalType "Int16"
instance HasStructuralInfo Int32 where structuralInfo _ = NominalType "Int32"
instance HasStructuralInfo Int64 where structuralInfo _ = NominalType "Int64"
instance HasStructuralInfo Word8 where structuralInfo _ = NominalType "Word8"
instance HasStructuralInfo Word16 where structuralInfo _ = NominalType "Word16"
instance HasStructuralInfo Word32 where structuralInfo _ = NominalType "Word32"
instance HasStructuralInfo Word64 where structuralInfo _ = NominalType "Word64"
instance HasSemanticVersion Bool
instance HasSemanticVersion Char
instance HasSemanticVersion Int
instance HasSemanticVersion Word
instance HasSemanticVersion Integer
instance HasSemanticVersion Int8
instance HasSemanticVersion Int16
instance HasSemanticVersion Int32
instance HasSemanticVersion Int64
instance HasSemanticVersion Word8
instance HasSemanticVersion Word16
instance HasSemanticVersion Word32
instance HasSemanticVersion Word64
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo Ordering where structuralInfo = ghcNominalType
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion Ordering
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo Float where structuralInfo _ = NominalType "Float"
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo Double where structuralInfo _ = NominalType "Double"
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion Float
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion Double
-- Recursive types
instance HasStructuralInfo a => HasStructuralInfo [a] where structuralInfo = ghcStructuralInfo1
instance HasSemanticVersion a => HasSemanticVersion [a] where
type SemanticVersion [a] = SemanticVersion a
-- Types from base
instance HasStructuralInfo a => HasStructuralInfo (Maybe a)
instance HasSemanticVersion a => HasSemanticVersion (Maybe a) where
type SemanticVersion (Maybe a) = SemanticVersion a
instance HasStructuralInfo a => HasStructuralInfo (Ratio.Ratio a) where
structuralInfo _ = NominalNewtype "Ratio" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (Ratio.Ratio a) where
type SemanticVersion (Ratio.Ratio a) = SemanticVersion a
instance (HasStructuralInfo a, HasStructuralInfo b) => HasStructuralInfo (Either a b)
instance (HasSemanticVersion a, HasSemanticVersion b, KnownNat (SemanticVersion (Either a b))) => HasSemanticVersion (Either a b) where
type SemanticVersion (Either a b) = Interleave (SemanticVersion a) (SemanticVersion b)
-- Tuples
instance (HasStructuralInfo a, HasStructuralInfo b) => HasStructuralInfo (a, b)
instance (HasStructuralInfo a, HasStructuralInfo b, HasStructuralInfo c) => HasStructuralInfo (a, b, c)
instance (HasStructuralInfo a, HasStructuralInfo b, HasStructuralInfo c, HasStructuralInfo d) => HasStructuralInfo (a, b, c, d)
instance (HasSemanticVersion a
,HasSemanticVersion b
,KnownNat (SemanticVersion (a, b))) => HasSemanticVersion (a, b) where
type SemanticVersion (a, b) = Interleave (SemanticVersion a) (SemanticVersion b)
-- | /Since binary-tagged-0.1.3.0/
instance (HasSemanticVersion a
,HasSemanticVersion b
,HasSemanticVersion c
,KnownNat (SemanticVersion (a, b, c))) => HasSemanticVersion (a, b, c) where
type SemanticVersion (a, b, c) = Interleave (SemanticVersion a) (SemanticVersion (b, c))
-- | /Since binary-tagged-0.1.3.0/
instance (HasSemanticVersion a
,HasSemanticVersion b
,HasSemanticVersion c
,HasSemanticVersion d
,KnownNat (SemanticVersion (a, b, c, d))) => HasSemanticVersion (a, b, c, d) where
type SemanticVersion (a, b, c, d) = Interleave (SemanticVersion a) (SemanticVersion (b, c, d))
-- Unit
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo () where structuralInfo _ = NominalType "()"
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion ()
-- Fixed
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo a => HasStructuralInfo (Fixed.Fixed a) where
structuralInfo _ = StructuralInfo "Fixed" [[ structuralInfo (Proxy :: Proxy a) ]]
instance HasStructuralInfo Fixed.E0 where structuralInfo _ = NominalType "E0"
instance HasStructuralInfo Fixed.E1 where structuralInfo _ = NominalType "E1"
instance HasStructuralInfo Fixed.E2 where structuralInfo _ = NominalType "E2"
instance HasStructuralInfo Fixed.E3 where structuralInfo _ = NominalType "E3"
instance HasStructuralInfo Fixed.E6 where structuralInfo _ = NominalType "E6"
instance HasStructuralInfo Fixed.E9 where structuralInfo _ = NominalType "E9"
instance HasStructuralInfo Fixed.E12 where structuralInfo _ = NominalType "E12"
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion (Fixed.Fixed a)
-- Version
-- | /Since binary-tagged-0.1.3.0/
instance HasStructuralInfo Version.Version where
structuralInfo _ = StructuralInfo "Version" [[ structuralInfo (Proxy :: Proxy [Int])
, structuralInfo (Proxy :: Proxy [String])
]]
-- Version has no Generic instance :(
-- | /Since binary-tagged-0.1.3.0/
instance HasSemanticVersion Version.Version
-- Monoid
instance HasStructuralInfo a => HasStructuralInfo (Monoid.Sum a)
instance HasSemanticVersion a => HasSemanticVersion (Monoid.Sum a) where
type SemanticVersion (Monoid.Sum a) = SemanticVersion a
instance HasStructuralInfo a => HasStructuralInfo (Monoid.Product a)
instance HasSemanticVersion a => HasSemanticVersion (Monoid.Product a) where
type SemanticVersion (Monoid.Product a) = SemanticVersion a
-- TODO: add more
-- ByteString
instance HasStructuralInfo BS.ByteString where structuralInfo _ = NominalType "ByteString.Strict"
instance HasStructuralInfo LBS.ByteString where structuralInfo _ = NominalType "ByteString.Lazy"
instance HasSemanticVersion BS.ByteString
instance HasSemanticVersion LBS.ByteString
-- Text
instance HasStructuralInfo S.Text where structuralInfo _ = NominalType "Text.Strict"
instance HasStructuralInfo L.Text where structuralInfo _ = NominalType "Text.Lazy"
instance HasSemanticVersion S.Text
instance HasSemanticVersion L.Text
-- Containers
instance HasStructuralInfo a => HasStructuralInfo (IntMap.IntMap a) where
structuralInfo _ = NominalNewtype "IntMap" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (IntMap.IntMap a) where
type SemanticVersion (IntMap.IntMap a) = SemanticVersion a
instance HasStructuralInfo IntSet.IntSet where
structuralInfo _ = NominalType "IntSet"
instance HasSemanticVersion IntSet.IntSet
instance (HasStructuralInfo k, HasStructuralInfo v) => HasStructuralInfo (Map.Map k v) where
structuralInfo _ = StructuralInfo "Map" [[ structuralInfo (Proxy :: Proxy k), structuralInfo (Proxy :: Proxy v) ]]
instance (HasSemanticVersion k, HasSemanticVersion v, KnownNat (SemanticVersion (Map.Map k v))) => HasSemanticVersion (Map.Map k v) where
type SemanticVersion (Map.Map k v) = Interleave (SemanticVersion k) (SemanticVersion v)
instance HasStructuralInfo a => HasStructuralInfo (Seq.Seq a) where
structuralInfo _ = NominalNewtype "Seq" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (Seq.Seq a) where
type SemanticVersion (Seq.Seq a) = SemanticVersion a
instance HasStructuralInfo a => HasStructuralInfo (Set.Set a) where
structuralInfo _ = NominalNewtype "Set" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (Set.Set a) where
type SemanticVersion (Set.Set a) = SemanticVersion a
-- Unordered containers
instance (HasStructuralInfo k, HasStructuralInfo v) => HasStructuralInfo (HML.HashMap k v) where
structuralInfo _ = StructuralInfo "HashMap" [[ structuralInfo (Proxy :: Proxy k), structuralInfo (Proxy :: Proxy v) ]]
instance (HasSemanticVersion k, HasSemanticVersion v, KnownNat (SemanticVersion (HML.HashMap k v))) => HasSemanticVersion (HML.HashMap k v) where
type SemanticVersion (HML.HashMap k v) = Interleave (SemanticVersion k) (SemanticVersion v)
instance HasStructuralInfo a => HasStructuralInfo (HS.HashSet a) where
structuralInfo _ = NominalNewtype "HashSet" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (HS.HashSet a) where
type SemanticVersion (HS.HashSet a) = SemanticVersion a
-- Array
instance (HasStructuralInfo i, HasStructuralInfo e) => HasStructuralInfo (Array.Array i e) where
structuralInfo _ = StructuralInfo "Array" [[ structuralInfo (Proxy :: Proxy i), structuralInfo (Proxy :: Proxy e) ]]
instance (HasSemanticVersion i, HasSemanticVersion e, KnownNat (SemanticVersion (Array.Array i e))) => HasSemanticVersion (Array.Array i e) where
type SemanticVersion (Array.Array i e) = Interleave (SemanticVersion i) (SemanticVersion e)
instance (HasStructuralInfo i, HasStructuralInfo e) => HasStructuralInfo (Array.UArray i e) where
structuralInfo _ = StructuralInfo "UArray" [[ structuralInfo (Proxy :: Proxy i), structuralInfo (Proxy :: Proxy e) ]]
instance (HasSemanticVersion i, HasSemanticVersion e, KnownNat (SemanticVersion (Array.UArray i e))) => HasSemanticVersion (Array.UArray i e) where
type SemanticVersion (Array.UArray i e) = Interleave (SemanticVersion i) (SemanticVersion e)
-- Vector
instance HasStructuralInfo a => HasStructuralInfo (V.Vector a) where
structuralInfo _ = NominalNewtype "Vector" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (V.Vector a) where
type SemanticVersion (V.Vector a) = SemanticVersion a
instance HasStructuralInfo a => HasStructuralInfo (U.Vector a) where
structuralInfo _ = NominalNewtype "Vector.Unboxed" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (U.Vector a) where
type SemanticVersion (U.Vector a) = SemanticVersion a
instance HasStructuralInfo a => HasStructuralInfo (S.Vector a) where
structuralInfo _ = NominalNewtype "Vector.Storable" $ structuralInfo (Proxy :: Proxy a)
instance HasSemanticVersion a => HasSemanticVersion (S.Vector a) where
type SemanticVersion (S.Vector a) = SemanticVersion a
-- Time
instance HasStructuralInfo Time.UTCTime where structuralInfo _ = NominalType "UTCTime"
instance HasStructuralInfo Time.DiffTime where structuralInfo _ = NominalType "DiffTime"
instance HasStructuralInfo Time.UniversalTime where structuralInfo _ = NominalType "UniversalTime"
instance HasStructuralInfo Time.NominalDiffTime where structuralInfo _ = NominalType "NominalDiffTime"
instance HasStructuralInfo Time.Day where structuralInfo _ = NominalType "Day"
instance HasStructuralInfo Time.TimeZone where structuralInfo _ = NominalType "TimeZone"
instance HasStructuralInfo Time.TimeOfDay where structuralInfo _ = NominalType "TimeOfDay"
instance HasStructuralInfo Time.LocalTime where structuralInfo _ = NominalType "LocalTime"
instance HasSemanticVersion Time.UTCTime
instance HasSemanticVersion Time.DiffTime
instance HasSemanticVersion Time.UniversalTime
instance HasSemanticVersion Time.NominalDiffTime
instance HasSemanticVersion Time.Day
instance HasSemanticVersion Time.TimeZone
instance HasSemanticVersion Time.TimeOfDay
instance HasSemanticVersion Time.LocalTime
-- Value
-- TODO: derive sop
instance HasStructuralInfo Aeson.Value where structuralInfo _ = NominalType "Aeson.Value"
instance HasSemanticVersion Aeson.Value