{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Extra.Solver #-}
{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver #-}
{-# OPTIONS_GHC -fplugin=GHC.TypeLits.Normalise #-}
{-# OPTIONS_HADDOCK hide #-}

{- |
Copyright  :  (C) 2025     , Martijn Bastiaan
License    :  BSD2 (see the file LICENSE)
Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>
-}
module Clash.Class.NumConvert.Internal.MaybeNumConvert where

import Clash.Class.BitPack
import Clash.Class.Resize
import Clash.Sized.BitVector
import Clash.Sized.Index
import Clash.Sized.Signed
import Clash.Sized.Unsigned

import GHC.TypeLits (KnownNat, type (+), type (<=), type (^))
import GHC.TypeLits.Extra (CLog)

import Data.Int (Int16, Int32, Int64, Int8)
import Data.Word (Word16, Word32, Word64, Word8)

{- $setup
>>> import Clash.Prelude
>>> import Clash.Class.NumConvert
-}

{- | Conversions that may fail for some values. A successful conversion retains
the numerical value interpretation of the source type in the target type. A
failure is expressed by returning 'Nothing', never by an 'Clash.XException.XException'.

== __Laws__
A conversion is either successful or it fails gracefully. I.e., it does not
produces produce errors (also see "Clash.XException"). I.e.,

> x == fromMaybe x (maybeNumConvert @a @b x >>= maybeNumConvert @b @a)

for all values @x@ of type @a@. It should also preserve the numerical value
interpretation of the bits. For types that have an @Integral@ instance, this
intuition is captured by:

> toInteger x == fromMaybe (toInteger x) (toInteger (numConvert @a @b x))

If a conversion succeeds one way, it should also succeed the other way. I.e.,

> isJust (maybeNumConvert @a @b x) `implies` isJust (maybeNumConvert @a @b x >>= maybeNumConvert @b @a)

A conversion should succeed if and only if the value is representable in the
target type. For types that have a @Bounded@ and @Integral@ instance, this
intuition is captured by:

> isJust (maybeNumConvert @a @b x) == (i x >= i (minBound @b) && i x <= i (maxBound @b))

where @i = toInteger@.

All implementations should be total, i.e., they should not produce \"bottoms\".

Additionally, any implementation should be translatable to synthesizable HDL.
-}
class MaybeNumConvert a b where
  {- | Convert a supplied value of type @a@ to a value of type @b@. If the value
    cannot be represented in the target type, 'Nothing' is returned.

    >>> maybeNumConvert (1 :: Index 8) :: Maybe (Unsigned 2)
    Just 1
    >>> maybeNumConvert (7 :: Index 8) :: Maybe (Unsigned 2)
    Nothing

    For the time being, if the input is an 'Clash.XException.XException', then
    the output is too. This property might be relaxed in the future.
  -}
  maybeNumConvert :: a -> Maybe b

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Index n) (Index m) where
  maybeNumConvert :: Index n -> Maybe (Index m)
maybeNumConvert !Index n
a = Index n -> Maybe (Index m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize Index n
a

instance (KnownNat n, KnownNat m, 1 <= n) => MaybeNumConvert (Index n) (Unsigned m) where
  maybeNumConvert :: Index n -> Maybe (Unsigned m)
maybeNumConvert !Index n
a = Unsigned (CLog 2 n) -> Maybe (Unsigned m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Unsigned (CLog 2 n) -> Maybe (Unsigned m))
-> Unsigned (CLog 2 n) -> Maybe (Unsigned m)
forall a b. (a -> b) -> a -> b
$ Index n -> Unsigned (CLog 2 n)
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned (CLog 2 n)) Index n
a

instance (KnownNat n, KnownNat m, 1 <= n) => MaybeNumConvert (Index n) (Signed m) where
  maybeNumConvert :: Index n -> Maybe (Signed m)
maybeNumConvert !Index n
a = Unsigned (CLog 2 n) -> Maybe (Signed m)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned (CLog 2 n) -> Maybe (Signed m))
-> Unsigned (CLog 2 n) -> Maybe (Signed m)
forall a b. (a -> b) -> a -> b
$ Index n -> Unsigned (CLog 2 n)
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned (CLog 2 n)) Index n
a

instance (KnownNat n, KnownNat m, 1 <= n) => MaybeNumConvert (Index n) (BitVector m) where
  maybeNumConvert :: Index n -> Maybe (BitVector m)
maybeNumConvert !Index n
a = BitVector (CLog 2 n) -> Maybe (BitVector m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (BitVector (CLog 2 n) -> Maybe (BitVector m))
-> BitVector (CLog 2 n) -> Maybe (BitVector m)
forall a b. (a -> b) -> a -> b
$ Index n -> BitVector (BitSize (Index n))
forall a. BitPack a => a -> BitVector (BitSize a)
pack Index n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Unsigned n) (Index m) where
  maybeNumConvert :: Unsigned n -> Maybe (Index m)
maybeNumConvert !Unsigned n
a = Index (2 ^ n) -> Maybe (Index m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Index (2 ^ n) -> Maybe (Index m))
-> Index (2 ^ n) -> Maybe (Index m)
forall a b. (a -> b) -> a -> b
$ Unsigned n -> Index (2 ^ n)
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Index (2 ^ n)) Unsigned n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Unsigned n) (Unsigned m) where
  maybeNumConvert :: Unsigned n -> Maybe (Unsigned m)
maybeNumConvert !Unsigned n
a = Unsigned n -> Maybe (Unsigned m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize Unsigned n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Unsigned n) (Signed m) where
  maybeNumConvert :: Unsigned n -> Maybe (Signed m)
maybeNumConvert !Unsigned n
a = Signed (n + 1) -> Maybe (Signed m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Signed (n + 1) -> Maybe (Signed m))
-> Signed (n + 1) -> Maybe (Signed m)
forall a b. (a -> b) -> a -> b
$ forall b.
(BitPack (Unsigned (n + 1)), BitPack b,
 BitSize (Unsigned (n + 1)) ~ BitSize b) =>
Unsigned (n + 1) -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned (n + 1)) (Unsigned (n + 1) -> Signed (n + 1))
-> Unsigned (n + 1) -> Signed (n + 1)
forall a b. (a -> b) -> a -> b
$ Unsigned n -> Unsigned (1 + n)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f (b + a)
extend Unsigned n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Unsigned n) (BitVector m) where
  maybeNumConvert :: Unsigned n -> Maybe (BitVector m)
maybeNumConvert !Unsigned n
a = BitVector n -> Maybe (BitVector m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (BitVector n -> Maybe (BitVector m))
-> BitVector n -> Maybe (BitVector m)
forall a b. (a -> b) -> a -> b
$ Unsigned n -> BitVector (BitSize (Unsigned n))
forall a. BitPack a => a -> BitVector (BitSize a)
pack Unsigned n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Signed n) (Index m) where
  maybeNumConvert :: Signed n -> Maybe (Index m)
maybeNumConvert Signed n
n
    | Signed n
n Signed n -> Signed n -> Bool
forall a. Ord a => a -> a -> Bool
< Signed n
0 = Maybe (Index m)
forall a. Maybe a
Nothing
    | Bool
otherwise = Index (2 ^ n) -> Maybe (Index m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Signed (CLog 2 (2 ^ n)) -> Index (2 ^ n)
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Index (2 ^ n)) (Signed n -> Signed (CLog 2 (2 ^ n))
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f b
resize Signed n
n))

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Signed n) (Unsigned m) where
  maybeNumConvert :: Signed n -> Maybe (Unsigned m)
maybeNumConvert Signed n
n
    | Signed n
n Signed n -> Signed n -> Bool
forall a. Ord a => a -> a -> Bool
< Signed n
0 = Maybe (Unsigned m)
forall a. Maybe a
Nothing
    | Bool
otherwise = Unsigned (n + 1) -> Maybe (Unsigned m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Signed (n + 1) -> Unsigned (n + 1)
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Signed (n + 1)) (Signed n -> Signed (1 + n)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f (b + a)
extend Signed n
n))

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Signed n) (Signed m) where
  maybeNumConvert :: Signed n -> Maybe (Signed m)
maybeNumConvert !Signed n
a = Signed n -> Maybe (Signed m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize Signed n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (Signed n) (BitVector m) where
  maybeNumConvert :: Signed n -> Maybe (BitVector m)
maybeNumConvert Signed n
n
    | Signed n
n Signed n -> Signed n -> Bool
forall a. Ord a => a -> a -> Bool
< Signed n
0 = Maybe (BitVector m)
forall a. Maybe a
Nothing
    | Bool
otherwise = BitVector (n + 1) -> Maybe (BitVector m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Signed (n + 1) -> BitVector (BitSize (Signed (n + 1)))
forall a. BitPack a => a -> BitVector (BitSize a)
pack @(Signed (n + 1)) (Signed n -> Signed (1 + n)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f (b + a)
extend Signed n
n))

instance (KnownNat n, KnownNat m) => MaybeNumConvert (BitVector n) (Index m) where
  maybeNumConvert :: BitVector n -> Maybe (Index m)
maybeNumConvert !BitVector n
a = Index (2 ^ n) -> Maybe (Index m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Index (2 ^ n) -> Maybe (Index m))
-> Index (2 ^ n) -> Maybe (Index m)
forall a b. (a -> b) -> a -> b
$ BitVector (BitSize (Index (2 ^ n))) -> Index (2 ^ n)
forall a. BitPack a => BitVector (BitSize a) -> a
unpack @(Index (2 ^ n)) BitVector n
BitVector (BitSize (Index (2 ^ n)))
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (BitVector n) (Unsigned m) where
  maybeNumConvert :: BitVector n -> Maybe (Unsigned m)
maybeNumConvert !BitVector n
a = Unsigned n -> Maybe (Unsigned m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Unsigned n -> Maybe (Unsigned m))
-> Unsigned n -> Maybe (Unsigned m)
forall a b. (a -> b) -> a -> b
$ BitVector (BitSize (Unsigned n)) -> Unsigned n
forall a. BitPack a => BitVector (BitSize a) -> a
unpack @(Unsigned n) BitVector n
BitVector (BitSize (Unsigned n))
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (BitVector n) (Signed m) where
  maybeNumConvert :: BitVector n -> Maybe (Signed m)
maybeNumConvert !BitVector n
a = Signed (n + 1) -> Maybe (Signed m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize (Signed (n + 1) -> Maybe (Signed m))
-> Signed (n + 1) -> Maybe (Signed m)
forall a b. (a -> b) -> a -> b
$ BitPack (Signed (n + 1)) =>
BitVector (BitSize (Signed (n + 1))) -> Signed (n + 1)
forall a. BitPack a => BitVector (BitSize a) -> a
unpack @(Signed (n + 1)) (BitVector (BitSize (Signed (n + 1))) -> Signed (n + 1))
-> BitVector (BitSize (Signed (n + 1))) -> Signed (n + 1)
forall a b. (a -> b) -> a -> b
$ BitVector n -> BitVector (1 + n)
forall (f :: Nat -> Type) (a :: Nat) (b :: Nat).
(Resize f, KnownNat a, KnownNat b) =>
f a -> f (b + a)
extend BitVector n
a

instance (KnownNat n, KnownNat m) => MaybeNumConvert (BitVector n) (BitVector m) where
  maybeNumConvert :: BitVector n -> Maybe (BitVector m)
maybeNumConvert !BitVector n
a = BitVector n -> Maybe (BitVector m)
forall (a :: Nat) (b :: Nat) (f :: Nat -> Type).
(Resize f, KnownNat a, Integral (f a), KnownNat b, Integral (f b),
 Bounded (f b)) =>
f a -> Maybe (f b)
maybeResize BitVector n
a

instance (MaybeNumConvert (Unsigned 64) a) => MaybeNumConvert Word a where
  maybeNumConvert :: Word -> Maybe a
maybeNumConvert !Word
a = Unsigned 64 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned 64 -> Maybe a) -> Unsigned 64 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word -> Unsigned 64
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned 64) Word
a
instance (MaybeNumConvert (Unsigned 64) a) => MaybeNumConvert Word64 a where
  maybeNumConvert :: Word64 -> Maybe a
maybeNumConvert !Word64
a = Unsigned 64 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned 64 -> Maybe a) -> Unsigned 64 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word64 -> Unsigned 64
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned 64) Word64
a
instance (MaybeNumConvert (Unsigned 32) a) => MaybeNumConvert Word32 a where
  maybeNumConvert :: Word32 -> Maybe a
maybeNumConvert !Word32
a = Unsigned 32 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned 32 -> Maybe a) -> Unsigned 32 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word32 -> Unsigned 32
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned 32) Word32
a
instance (MaybeNumConvert (Unsigned 16) a) => MaybeNumConvert Word16 a where
  maybeNumConvert :: Word16 -> Maybe a
maybeNumConvert !Word16
a = Unsigned 16 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned 16 -> Maybe a) -> Unsigned 16 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word16 -> Unsigned 16
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned 16) Word16
a
instance (MaybeNumConvert (Unsigned 8) a) => MaybeNumConvert Word8 a where
  maybeNumConvert :: Word8 -> Maybe a
maybeNumConvert !Word8
a = Unsigned 8 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Unsigned 8 -> Maybe a) -> Unsigned 8 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Word8 -> Unsigned 8
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Unsigned 8) Word8
a

instance (MaybeNumConvert (Signed 64) a) => MaybeNumConvert Int a where
  maybeNumConvert :: Int -> Maybe a
maybeNumConvert !Int
a = Signed 64 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Signed 64 -> Maybe a) -> Signed 64 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int -> Signed 64
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Signed 64) Int
a
instance (MaybeNumConvert (Signed 64) a) => MaybeNumConvert Int64 a where
  maybeNumConvert :: Int64 -> Maybe a
maybeNumConvert !Int64
a = Signed 64 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Signed 64 -> Maybe a) -> Signed 64 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int64 -> Signed 64
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Signed 64) Int64
a
instance (MaybeNumConvert (Signed 32) a) => MaybeNumConvert Int32 a where
  maybeNumConvert :: Int32 -> Maybe a
maybeNumConvert !Int32
a = Signed 32 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Signed 32 -> Maybe a) -> Signed 32 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int32 -> Signed 32
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Signed 32) Int32
a
instance (MaybeNumConvert (Signed 16) a) => MaybeNumConvert Int16 a where
  maybeNumConvert :: Int16 -> Maybe a
maybeNumConvert !Int16
a = Signed 16 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Signed 16 -> Maybe a) -> Signed 16 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int16 -> Signed 16
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Signed 16) Int16
a
instance (MaybeNumConvert (Signed 8) a) => MaybeNumConvert Int8 a where
  maybeNumConvert :: Int8 -> Maybe a
maybeNumConvert !Int8
a = Signed 8 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Signed 8 -> Maybe a) -> Signed 8 -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int8 -> Signed 8
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @_ @(Signed 8) Int8
a

instance (MaybeNumConvert a (Unsigned 64)) => MaybeNumConvert a Word where
  maybeNumConvert :: a -> Maybe Word
maybeNumConvert !a
a = (Unsigned 64 -> Word) -> Maybe (Unsigned 64) -> Maybe Word
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Unsigned 64), BitPack b,
 BitSize (Unsigned 64) ~ BitSize b) =>
Unsigned 64 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned 64)) (Maybe (Unsigned 64) -> Maybe Word)
-> Maybe (Unsigned 64) -> Maybe Word
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Unsigned 64)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Unsigned 64)) => MaybeNumConvert a Word64 where
  maybeNumConvert :: a -> Maybe Word64
maybeNumConvert !a
a = (Unsigned 64 -> Word64) -> Maybe (Unsigned 64) -> Maybe Word64
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Unsigned 64), BitPack b,
 BitSize (Unsigned 64) ~ BitSize b) =>
Unsigned 64 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned 64)) (Maybe (Unsigned 64) -> Maybe Word64)
-> Maybe (Unsigned 64) -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Unsigned 64)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Unsigned 32)) => MaybeNumConvert a Word32 where
  maybeNumConvert :: a -> Maybe Word32
maybeNumConvert !a
a = (Unsigned 32 -> Word32) -> Maybe (Unsigned 32) -> Maybe Word32
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Unsigned 32), BitPack b,
 BitSize (Unsigned 32) ~ BitSize b) =>
Unsigned 32 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned 32)) (Maybe (Unsigned 32) -> Maybe Word32)
-> Maybe (Unsigned 32) -> Maybe Word32
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Unsigned 32)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Unsigned 16)) => MaybeNumConvert a Word16 where
  maybeNumConvert :: a -> Maybe Word16
maybeNumConvert !a
a = (Unsigned 16 -> Word16) -> Maybe (Unsigned 16) -> Maybe Word16
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Unsigned 16), BitPack b,
 BitSize (Unsigned 16) ~ BitSize b) =>
Unsigned 16 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned 16)) (Maybe (Unsigned 16) -> Maybe Word16)
-> Maybe (Unsigned 16) -> Maybe Word16
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Unsigned 16)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Unsigned 8)) => MaybeNumConvert a Word8 where
  maybeNumConvert :: a -> Maybe Word8
maybeNumConvert !a
a = (Unsigned 8 -> Word8) -> Maybe (Unsigned 8) -> Maybe Word8
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Unsigned 8), BitPack b,
 BitSize (Unsigned 8) ~ BitSize b) =>
Unsigned 8 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Unsigned 8)) (Maybe (Unsigned 8) -> Maybe Word8)
-> Maybe (Unsigned 8) -> Maybe Word8
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Unsigned 8)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a

instance (MaybeNumConvert a (Signed 64)) => MaybeNumConvert a Int64 where
  maybeNumConvert :: a -> Maybe Int64
maybeNumConvert !a
a = (Signed 64 -> Int64) -> Maybe (Signed 64) -> Maybe Int64
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Signed 64), BitPack b,
 BitSize (Signed 64) ~ BitSize b) =>
Signed 64 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Signed 64)) (Maybe (Signed 64) -> Maybe Int64)
-> Maybe (Signed 64) -> Maybe Int64
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Signed 64)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Signed 32)) => MaybeNumConvert a Int32 where
  maybeNumConvert :: a -> Maybe Int32
maybeNumConvert !a
a = (Signed 32 -> Int32) -> Maybe (Signed 32) -> Maybe Int32
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Signed 32), BitPack b,
 BitSize (Signed 32) ~ BitSize b) =>
Signed 32 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Signed 32)) (Maybe (Signed 32) -> Maybe Int32)
-> Maybe (Signed 32) -> Maybe Int32
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Signed 32)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Signed 16)) => MaybeNumConvert a Int16 where
  maybeNumConvert :: a -> Maybe Int16
maybeNumConvert !a
a = (Signed 16 -> Int16) -> Maybe (Signed 16) -> Maybe Int16
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Signed 16), BitPack b,
 BitSize (Signed 16) ~ BitSize b) =>
Signed 16 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Signed 16)) (Maybe (Signed 16) -> Maybe Int16)
-> Maybe (Signed 16) -> Maybe Int16
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Signed 16)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert a (Signed 8)) => MaybeNumConvert a Int8 where
  maybeNumConvert :: a -> Maybe Int8
maybeNumConvert !a
a = (Signed 8 -> Int8) -> Maybe (Signed 8) -> Maybe Int8
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall b.
(BitPack (Signed 8), BitPack b, BitSize (Signed 8) ~ BitSize b) =>
Signed 8 -> b
forall a b. (BitPack a, BitPack b, BitSize a ~ BitSize b) => a -> b
bitCoerce @(Signed 8)) (Maybe (Signed 8) -> Maybe Int8) -> Maybe (Signed 8) -> Maybe Int8
forall a b. (a -> b) -> a -> b
$ a -> Maybe (Signed 8)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a

instance (MaybeNumConvert a (BitVector 1)) => MaybeNumConvert a Bit where
  maybeNumConvert :: a -> Maybe Bit
maybeNumConvert !a
a = BitVector 1 -> Bit
forall a. BitPack a => BitVector (BitSize a) -> a
unpack (BitVector 1 -> Bit) -> Maybe (BitVector 1) -> Maybe Bit
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> Maybe (BitVector 1)
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert a
a
instance (MaybeNumConvert (BitVector 1) a) => MaybeNumConvert Bit a where
  maybeNumConvert :: Bit -> Maybe a
maybeNumConvert !Bit
a = BitVector 1 -> Maybe a
forall a b. MaybeNumConvert a b => a -> Maybe b
maybeNumConvert (Bit -> BitVector (BitSize Bit)
forall a. BitPack a => a -> BitVector (BitSize a)
pack Bit
a)