    module Basement.NormalForm
        ( NormalForm(..)
        , deepseq
        , force
        ) where

    import Basement.Compat.Base
    import Basement.Compat.C.Types
    import Basement.Compat.Natural
    import Basement.Types.OffsetSize
    import Basement.Types.Char7
    import Basement.Types.Word128 (Word128)
    import Basement.Types.Word256 (Word256)
    import Basement.Bounded
    import Basement.Endianness

    -- | Data that can be fully evaluated in Normal Form
    --
    class NormalForm a where
        toNormalForm :: a -> ()

    deepseq :: NormalForm a => a -> b -> b
    deepseq :: forall a b. NormalForm a => a -> b -> b
    deepseq a
    a b
    b = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> b -> b
    forall a b. a -> b -> b
    `seq` b
    b

    force :: NormalForm a => a -> a
    force :: forall a. NormalForm a => a -> a
    force a
    a = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> a -> a
    forall a b. a -> b -> b
    `seq` a
    a

    -----
    -- GHC / base types

    instance NormalForm Int8    where toNormalForm :: Int8 -> ()
    toNormalForm !Int8
    _ = ()
    instance NormalForm Int16   where toNormalForm :: Int16 -> ()
    toNormalForm !Int16
    _ = ()
    instance NormalForm Int32   where toNormalForm :: Int32 -> ()
    toNormalForm !Int32
    _ = ()
    instance NormalForm Int64   where toNormalForm :: Int64 -> ()
    toNormalForm !Int64
    _ = ()
    instance NormalForm Int     where toNormalForm :: Int -> ()
    toNormalForm !Int
    _ = ()
    instance NormalForm Integer where toNormalForm :: Integer -> ()
    toNormalForm !Integer
    _ = ()

    instance NormalForm Word8   where toNormalForm :: Word8 -> ()
    toNormalForm !Word8
    _ = ()
    instance NormalForm Word16  where toNormalForm :: Word16 -> ()
    toNormalForm !Word16
    _ = ()
    instance NormalForm Word32  where toNormalForm :: Word32 -> ()
    toNormalForm !Word32
    _ = ()
    instance NormalForm Word64  where toNormalForm :: Word64 -> ()
    toNormalForm !Word64
    _ = ()
    instance NormalForm Word    where toNormalForm :: Word -> ()
    toNormalForm !Word
    _ = ()
    instance NormalForm Natural where toNormalForm :: Natural -> ()
    toNormalForm !Natural
    _ = ()

    instance NormalForm Float  where toNormalForm :: Float -> ()
    toNormalForm !Float
    _ = ()
    instance NormalForm Double where toNormalForm :: Double -> ()
    toNormalForm !Double
    _ = ()

    instance NormalForm Char where toNormalForm :: Char -> ()
    toNormalForm !Char
    _ = ()
    instance NormalForm Bool where toNormalForm :: Bool -> ()
    toNormalForm !Bool
    _ = ()
    instance NormalForm ()   where toNormalForm :: () -> ()
    toNormalForm !()
    _ = ()

    -----
    -- C Types
    instance NormalForm CChar  where toNormalForm :: CChar -> ()
    toNormalForm !CChar
    _ = ()
    instance NormalForm CUChar where toNormalForm :: CUChar -> ()
    toNormalForm !CUChar
    _ = ()
    instance NormalForm CSChar where toNormalForm :: CSChar -> ()
    toNormalForm !CSChar
    _ = ()

    instance NormalForm CShort  where toNormalForm :: CShort -> ()
    toNormalForm !CShort
    _ = ()
    instance NormalForm CUShort where toNormalForm :: CUShort -> ()
    toNormalForm !CUShort
    _ = ()
    instance NormalForm CInt    where toNormalForm :: CInt -> ()
    toNormalForm !CInt
    _ = ()
    instance NormalForm CUInt   where toNormalForm :: CUInt -> ()
    toNormalForm !CUInt
    _ = ()
    instance NormalForm CLong   where toNormalForm :: CLong -> ()
    toNormalForm !CLong
    _ = ()
    instance NormalForm CULong  where toNormalForm :: CULong -> ()
    toNormalForm !CULong
    _ = ()
    instance NormalForm CLLong  where toNormalForm :: CLLong -> ()
    toNormalForm !CLLong
    _ = ()
    instance NormalForm CULLong where toNormalForm :: CULLong -> ()
    toNormalForm !CULLong
    _ = ()

    instance NormalForm CFloat  where toNormalForm :: CFloat -> ()
    toNormalForm !CFloat
    _ = ()
    instance NormalForm CDouble where toNormalForm :: CDouble -> ()
    toNormalForm !CDouble
    _ = ()

    instance NormalForm (Ptr a) where toNormalForm :: Ptr a -> ()
    toNormalForm !Ptr a
    _ = ()

    -----
    -- Basic Foundation primitive types
    instance NormalForm (Offset a) where toNormalForm :: Offset a -> ()
    toNormalForm !Offset a
    _ = ()
    instance NormalForm (CountOf a) where toNormalForm :: CountOf a -> ()
    toNormalForm !CountOf a
    _ = ()

    instance NormalForm Char7 where toNormalForm :: Char7 -> ()
    toNormalForm !Char7
    _ = ()
    instance NormalForm Word128 where toNormalForm :: Word128 -> ()
    toNormalForm !Word128
    _ = ()
    instance NormalForm Word256 where toNormalForm :: Word256 -> ()
    toNormalForm !Word256
    _ = ()
    instance NormalForm (Zn n) where toNormalForm :: Zn n -> ()
    toNormalForm = Natural -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm (Natural -> ()) -> (Zn n -> Natural) -> Zn n -> ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Zn n -> Natural
    forall (n :: Natural). Zn n -> Natural
    unZn
    instance NormalForm (Zn64 n) where toNormalForm :: Zn64 n -> ()
    toNormalForm = Word64 -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm (Word64 -> ()) -> (Zn64 n -> Word64) -> Zn64 n -> ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Zn64 n -> Word64
    forall (n :: Natural). Zn64 n -> Word64
    unZn64

    -----
    -- composed type

    instance NormalForm a => NormalForm (Maybe a) where
        toNormalForm :: Maybe a -> ()
    toNormalForm Maybe a
    Nothing  = ()
        toNormalForm (Just a
    a) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()
    instance (NormalForm l, NormalForm r) => NormalForm (Either l r) where
        toNormalForm :: Either l r -> ()
    toNormalForm (Left l
    l)  = l -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm l
    l () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()
        toNormalForm (Right r
    r) = r -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm r
    r () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()
    instance NormalForm a => NormalForm (LE a) where
        toNormalForm :: LE a -> ()
    toNormalForm (LE a
    a) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()
    instance NormalForm a => NormalForm (BE a) where
        toNormalForm :: BE a -> ()
    toNormalForm (BE a
    a) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` ()

    instance NormalForm a => NormalForm [a] where
        toNormalForm :: [a] -> ()
    toNormalForm []     = ()
        toNormalForm (a
    x:[a]
    xs) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    x () -> () -> ()
    forall a b. a -> b -> b
    `seq` [a] -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm [a]
    xs

    instance (NormalForm a, NormalForm b) => NormalForm (a,b) where
        toNormalForm :: (a, b) -> ()
    toNormalForm (a
    a,b
    b) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b

    instance (NormalForm a, NormalForm b, NormalForm c) => NormalForm (a,b,c) where
        toNormalForm :: (a, b, c) -> ()
    toNormalForm (a
    a,b
    b,c
    c) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c

    instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d) => NormalForm (a,b,c,d) where
        toNormalForm :: (a, b, c, d) -> ()
    toNormalForm (a
    a,b
    b,c
    c,d
    d) = a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c () -> () -> ()
    forall a b. a -> b -> b
    `seq` d -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm d
    d

    instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e)
          => NormalForm (a,b,c,d,e) where
        toNormalForm :: (a, b, c, d, e) -> ()
    toNormalForm (a
    a,b
    b,c
    c,d
    d,e
    e) =
            a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c () -> () -> ()
    forall a b. a -> b -> b
    `seq` d -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm d
    d () -> () -> ()
    forall a b. a -> b -> b
    `seq`
            e -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm e
    e

    instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f)
          => NormalForm (a,b,c,d,e,f) where
        toNormalForm :: (a, b, c, d, e, f) -> ()
    toNormalForm (a
    a,b
    b,c
    c,d
    d,e
    e,f
    f) =
            a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c () -> () -> ()
    forall a b. a -> b -> b
    `seq` d -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm d
    d () -> () -> ()
    forall a b. a -> b -> b
    `seq`
            e -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm e
    e () -> () -> ()
    forall a b. a -> b -> b
    `seq` f -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm f
    f

    instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f, NormalForm g)
          => NormalForm (a,b,c,d,e,f,g) where
        toNormalForm :: (a, b, c, d, e, f, g) -> ()
    toNormalForm (a
    a,b
    b,c
    c,d
    d,e
    e,f
    f,g
    g) =
            a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c () -> () -> ()
    forall a b. a -> b -> b
    `seq` d -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm d
    d () -> () -> ()
    forall a b. a -> b -> b
    `seq`
            e -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm e
    e () -> () -> ()
    forall a b. a -> b -> b
    `seq` f -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm f
    f () -> () -> ()
    forall a b. a -> b -> b
    `seq` g -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm g
    g
    instance (NormalForm a, NormalForm b, NormalForm c, NormalForm d, NormalForm e, NormalForm f, NormalForm g, NormalForm h)
          => NormalForm (a,b,c,d,e,f,g,h) where
        toNormalForm :: (a, b, c, d, e, f, g, h) -> ()
    toNormalForm (a
    a,b
    b,c
    c,d
    d,e
    e,f
    f,g
    g,h
    h) =
            a -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm a
    a () -> () -> ()
    forall a b. a -> b -> b
    `seq` b -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm b
    b () -> () -> ()
    forall a b. a -> b -> b
    `seq` c -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm c
    c () -> () -> ()
    forall a b. a -> b -> b
    `seq` d -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm d
    d () -> () -> ()
    forall a b. a -> b -> b
    `seq`
            e -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm e
    e () -> () -> ()
    forall a b. a -> b -> b
    `seq` f -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm f
    f () -> () -> ()
    forall a b. a -> b -> b
    `seq` g -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm g
    g () -> () -> ()
    forall a b. a -> b -> b
    `seq` h -> ()
    forall a. NormalForm a => a -> ()
    toNormalForm h
    h