{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UndecidableSuperClasses #-}


module DataFrame.Internal.Nullable (
    
    BaseType,

    
    NullableArithOp (..),

    
    NullableCmpOp (..),

    
    NullLift1Op (..),
    NullLift2Op (..),

    
    NullLift1Result,
    NullLift2Result,

    
    NullCmpResult,

    
    NumericWidenOp (..),
    widenArithOp,
    WidenResult,

    
    DivWidenOp (..),
    divArithOp,
    WidenResultDiv,
) where

import Data.Int (Int32, Int64)
import DataFrame.Internal.Column (Columnable)
import DataFrame.Internal.Types (Promote, PromoteDiv)


type family BaseType a where
    BaseType (Maybe a) = a
    BaseType a = a


class
    ( Columnable a
    , Columnable b
    , Columnable c
    ) =>
    NullableArithOp a b c
        | a b -> c
    where
    
    nullArithOp ::
        (BaseType a -> BaseType a -> BaseType a) ->
        a ->
        b ->
        c


type family NullCmpResult a b where
    NullCmpResult (Maybe a) b = Maybe Bool
    NullCmpResult a (Maybe b) = Maybe Bool
    NullCmpResult a b = Bool


class
    ( Columnable a
    , Columnable b
    , Columnable e
    ) =>
    NullableCmpOp a b e
    where
    
    nullCmpOp ::
        (BaseType a -> BaseType a -> Bool) ->
        a ->
        b ->
        e


instance
    {-# OVERLAPPABLE #-}
    (Columnable a, a ~ BaseType a) =>
    NullableArithOp a a a
    where
    nullArithOp :: (BaseType a -> BaseType a -> BaseType a) -> a -> a -> a
nullArithOp BaseType a -> BaseType a -> BaseType a
f = a -> a -> a
BaseType a -> BaseType a -> BaseType a
f

instance
    {-# OVERLAPPABLE #-}
    (Columnable a, Columnable Bool, a ~ BaseType a) =>
    NullableCmpOp a a Bool
    where
    nullCmpOp :: (BaseType a -> BaseType a -> Bool) -> a -> a -> Bool
nullCmpOp BaseType a -> BaseType a -> Bool
f = a -> a -> Bool
BaseType a -> BaseType a -> Bool
f


instance
    (Columnable a, Columnable (Maybe a)) =>
    NullableArithOp (Maybe a) a (Maybe a)
    where
    nullArithOp :: (BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a))
-> Maybe a -> a -> Maybe a
nullArithOp BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f Maybe a
Nothing a
_ = Maybe a
forall a. Maybe a
Nothing
    nullArithOp BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f (Just a
x) a
y = a -> Maybe a
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f a
BaseType (Maybe a)
x a
BaseType (Maybe a)
y)

instance
    (Columnable a, Columnable (Maybe a), Columnable (Maybe Bool)) =>
    NullableCmpOp (Maybe a) a (Maybe Bool)
    where
    nullCmpOp :: (BaseType (Maybe a) -> BaseType (Maybe a) -> Bool)
-> Maybe a -> a -> Maybe Bool
nullCmpOp BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f Maybe a
Nothing a
_ = Maybe Bool
forall a. Maybe a
Nothing
    nullCmpOp BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f (Just a
x) a
y = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f a
BaseType (Maybe a)
x a
BaseType (Maybe a)
y)


instance
    ( Columnable a
    , Columnable (Maybe a)
    , a ~ BaseType a
    ) =>
    NullableArithOp a (Maybe a) (Maybe a)
    where
    nullArithOp :: (BaseType a -> BaseType a -> BaseType a) -> a -> Maybe a -> Maybe a
nullArithOp BaseType a -> BaseType a -> BaseType a
f a
_ Maybe a
Nothing = Maybe a
forall a. Maybe a
Nothing
    nullArithOp BaseType a -> BaseType a -> BaseType a
f a
x (Just a
y) = a -> Maybe a
forall a. a -> Maybe a
Just (BaseType a -> BaseType a -> BaseType a
f a
BaseType a
x a
BaseType a
y)

instance
    ( Columnable a
    , Columnable (Maybe a)
    , Columnable (Maybe Bool)
    , a ~ BaseType a
    ) =>
    NullableCmpOp a (Maybe a) (Maybe Bool)
    where
    nullCmpOp :: (BaseType a -> BaseType a -> Bool) -> a -> Maybe a -> Maybe Bool
nullCmpOp BaseType a -> BaseType a -> Bool
f a
_ Maybe a
Nothing = Maybe Bool
forall a. Maybe a
Nothing
    nullCmpOp BaseType a -> BaseType a -> Bool
f a
x (Just a
y) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (BaseType a -> BaseType a -> Bool
f a
BaseType a
x a
BaseType a
y)


instance
    {-# OVERLAPPING #-}
    (Columnable a, Columnable (Maybe a)) =>
    NullableArithOp (Maybe a) (Maybe a) (Maybe a)
    where
    nullArithOp :: (BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a))
-> Maybe a -> Maybe a -> Maybe a
nullArithOp BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f Maybe a
Nothing Maybe a
_ = Maybe a
forall a. Maybe a
Nothing
    nullArithOp BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f Maybe a
_ Maybe a
Nothing = Maybe a
forall a. Maybe a
Nothing
    nullArithOp BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f (Just a
x) (Just a
y) = a -> Maybe a
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType (Maybe a) -> BaseType (Maybe a)
f a
BaseType (Maybe a)
x a
BaseType (Maybe a)
y)

instance
    {-# OVERLAPPING #-}
    (Columnable a, Columnable (Maybe a), Columnable (Maybe Bool)) =>
    NullableCmpOp (Maybe a) (Maybe a) (Maybe Bool)
    where
    nullCmpOp :: (BaseType (Maybe a) -> BaseType (Maybe a) -> Bool)
-> Maybe a -> Maybe a -> Maybe Bool
nullCmpOp BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f Maybe a
Nothing Maybe a
_ = Maybe Bool
forall a. Maybe a
Nothing
    nullCmpOp BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f Maybe a
_ Maybe a
Nothing = Maybe Bool
forall a. Maybe a
Nothing
    nullCmpOp BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f (Just a
x) (Just a
y) = Bool -> Maybe Bool
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType (Maybe a) -> Bool
f a
BaseType (Maybe a)
x a
BaseType (Maybe a)
y)








type family NullLift1Result a r where
    NullLift1Result (Maybe a) r = Maybe r
    NullLift1Result a r = r

class
    ( Columnable a
    , Columnable r
    , Columnable c
    ) =>
    NullLift1Op a r c
    where
    applyNull1 :: (BaseType a -> r) -> a -> c


instance
    {-# OVERLAPPABLE #-}
    (Columnable a, Columnable r, a ~ BaseType a) =>
    NullLift1Op a r r
    where
    applyNull1 :: (BaseType a -> r) -> a -> r
applyNull1 BaseType a -> r
f = a -> r
BaseType a -> r
f


instance
    {-# OVERLAPPING #-}
    (Columnable a, Columnable r, Columnable (Maybe r)) =>
    NullLift1Op (Maybe a) r (Maybe r)
    where
    applyNull1 :: (BaseType (Maybe a) -> r) -> Maybe a -> Maybe r
applyNull1 BaseType (Maybe a) -> r
_ Maybe a
Nothing = Maybe r
forall a. Maybe a
Nothing
    applyNull1 BaseType (Maybe a) -> r
f (Just a
x) = r -> Maybe r
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> r
f a
BaseType (Maybe a)
x)








type family NullLift2Result a b r where
    NullLift2Result (Maybe a) b r = Maybe r
    NullLift2Result a (Maybe b) r = Maybe r
    NullLift2Result a b r = r

class
    ( Columnable a
    , Columnable b
    , Columnable r
    , Columnable c
    ) =>
    NullLift2Op a b r c
    where
    applyNull2 :: (BaseType a -> BaseType b -> r) -> a -> b -> c


instance
    {-# OVERLAPPABLE #-}
    (Columnable a, Columnable b, Columnable r, a ~ BaseType a, b ~ BaseType b) =>
    NullLift2Op a b r r
    where
    applyNull2 :: (BaseType a -> BaseType b -> r) -> a -> b -> r
applyNull2 BaseType a -> BaseType b -> r
f = a -> b -> r
BaseType a -> BaseType b -> r
f


instance
    {-# OVERLAPPABLE #-}
    (Columnable a, Columnable b, Columnable r, Columnable (Maybe r), b ~ BaseType b) =>
    NullLift2Op (Maybe a) b r (Maybe r)
    where
    applyNull2 :: (BaseType (Maybe a) -> BaseType b -> r) -> Maybe a -> b -> Maybe r
applyNull2 BaseType (Maybe a) -> BaseType b -> r
_ Maybe a
Nothing b
_ = Maybe r
forall a. Maybe a
Nothing
    applyNull2 BaseType (Maybe a) -> BaseType b -> r
f (Just a
x) b
y = r -> Maybe r
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType b -> r
f a
BaseType (Maybe a)
x b
BaseType b
y)


instance
    {-# OVERLAPPABLE #-}
    (Columnable a, Columnable b, Columnable r, Columnable (Maybe r), a ~ BaseType a) =>
    NullLift2Op a (Maybe b) r (Maybe r)
    where
    applyNull2 :: (BaseType a -> BaseType (Maybe b) -> r) -> a -> Maybe b -> Maybe r
applyNull2 BaseType a -> BaseType (Maybe b) -> r
_ a
_ Maybe b
Nothing = Maybe r
forall a. Maybe a
Nothing
    applyNull2 BaseType a -> BaseType (Maybe b) -> r
f a
x (Just b
y) = r -> Maybe r
forall a. a -> Maybe a
Just (BaseType a -> BaseType (Maybe b) -> r
f a
BaseType a
x b
BaseType (Maybe b)
y)


instance
    {-# OVERLAPPING #-}
    (Columnable a, Columnable b, Columnable r, Columnable (Maybe r)) =>
    NullLift2Op (Maybe a) (Maybe b) r (Maybe r)
    where
    applyNull2 :: (BaseType (Maybe a) -> BaseType (Maybe b) -> r)
-> Maybe a -> Maybe b -> Maybe r
applyNull2 BaseType (Maybe a) -> BaseType (Maybe b) -> r
_ Maybe a
Nothing Maybe b
_ = Maybe r
forall a. Maybe a
Nothing
    applyNull2 BaseType (Maybe a) -> BaseType (Maybe b) -> r
_ Maybe a
_ Maybe b
Nothing = Maybe r
forall a. Maybe a
Nothing
    applyNull2 BaseType (Maybe a) -> BaseType (Maybe b) -> r
f (Just a
x) (Just b
y) = r -> Maybe r
forall a. a -> Maybe a
Just (BaseType (Maybe a) -> BaseType (Maybe b) -> r
f a
BaseType (Maybe a)
x b
BaseType (Maybe b)
y)






class (Columnable (Promote a b)) => NumericWidenOp a b where
    widen1 :: a -> Promote a b
    widen2 :: b -> Promote a b


instance {-# OVERLAPPING #-} (Columnable a) => NumericWidenOp a a where
    widen1 :: a -> Promote a a
widen1 = a -> a
a -> Promote a a
forall a. a -> a
id
    widen2 :: a -> Promote a a
widen2 = a -> a
a -> Promote a a
forall a. a -> a
id

instance NumericWidenOp Int Double where widen1 :: Int -> Promote Int Double
widen1 = Int -> Double
Int -> Promote Int Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral; widen2 :: Double -> Promote Int Double
widen2 = Double -> Double
Double -> Promote Int Double
forall a. a -> a
id
instance NumericWidenOp Double Int where
    widen1 :: Double -> Promote Double Int
widen1 = Double -> Double
Double -> Promote Double Int
forall a. a -> a
id
    widen2 :: Int -> Promote Double Int
widen2 = Int -> Double
Int -> Promote Double Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance NumericWidenOp Float Double where widen1 :: Float -> Promote Float Double
widen1 = Float -> Double
Float -> Promote Float Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac; widen2 :: Double -> Promote Float Double
widen2 = Double -> Double
Double -> Promote Float Double
forall a. a -> a
id
instance NumericWidenOp Double Float where
    widen1 :: Double -> Promote Double Float
widen1 = Double -> Double
Double -> Promote Double Float
forall a. a -> a
id
    widen2 :: Float -> Promote Double Float
widen2 = Float -> Double
Float -> Promote Double Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac
instance NumericWidenOp Int Float where widen1 :: Int -> Promote Int Float
widen1 = Int -> Float
Int -> Promote Int Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral; widen2 :: Float -> Promote Int Float
widen2 = Float -> Float
Float -> Promote Int Float
forall a. a -> a
id
instance NumericWidenOp Float Int where
    widen1 :: Float -> Promote Float Int
widen1 = Float -> Float
Float -> Promote Float Int
forall a. a -> a
id
    widen2 :: Int -> Promote Float Int
widen2 = Int -> Float
Int -> Promote Float Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral


widenArithOp ::
    forall a b.
    (NumericWidenOp a b) =>
    (Promote a b -> Promote a b -> Promote a b) ->
    a ->
    b ->
    Promote a b
widenArithOp :: forall a b.
NumericWidenOp a b =>
(Promote a b -> Promote a b -> Promote a b)
-> a -> b -> Promote a b
widenArithOp Promote a b -> Promote a b -> Promote a b
f a
x b
y = Promote a b -> Promote a b -> Promote a b
f (forall a b. NumericWidenOp a b => a -> Promote a b
widen1 @a @b a
x) (forall a b. NumericWidenOp a b => b -> Promote a b
widen2 @a @b b
y)


type WidenResult a b = NullLift2Result a b (Promote (BaseType a) (BaseType b))






class (Columnable (PromoteDiv a b)) => DivWidenOp a b where
    divWiden1 :: a -> PromoteDiv a b
    divWiden2 :: b -> PromoteDiv a b


instance DivWidenOp Double Double where divWiden1 :: Double -> PromoteDiv Double Double
divWiden1 = Double -> Double
Double -> PromoteDiv Double Double
forall a. a -> a
id; divWiden2 :: Double -> PromoteDiv Double Double
divWiden2 = Double -> Double
Double -> PromoteDiv Double Double
forall a. a -> a
id
instance DivWidenOp Float Float where divWiden1 :: Float -> PromoteDiv Float Float
divWiden1 = Float -> Float
Float -> PromoteDiv Float Float
forall a. a -> a
id; divWiden2 :: Float -> PromoteDiv Float Float
divWiden2 = Float -> Float
Float -> PromoteDiv Float Float
forall a. a -> a
id


instance DivWidenOp Double Float where divWiden1 :: Double -> PromoteDiv Double Float
divWiden1 = Double -> Double
Double -> PromoteDiv Double Float
forall a. a -> a
id; divWiden2 :: Float -> PromoteDiv Double Float
divWiden2 = Float -> Double
Float -> PromoteDiv Double Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac
instance DivWidenOp Float Double where divWiden1 :: Float -> PromoteDiv Float Double
divWiden1 = Float -> Double
Float -> PromoteDiv Float Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac; divWiden2 :: Double -> PromoteDiv Float Double
divWiden2 = Double -> Double
Double -> PromoteDiv Float Double
forall a. a -> a
id


instance DivWidenOp Double Int where divWiden1 :: Double -> PromoteDiv Double Int
divWiden1 = Double -> Double
Double -> PromoteDiv Double Int
forall a. a -> a
id; divWiden2 :: Int -> PromoteDiv Double Int
divWiden2 = Int -> Double
Int -> PromoteDiv Double Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int Double where divWiden1 :: Int -> PromoteDiv Int Double
divWiden1 = Int -> Double
Int -> PromoteDiv Int Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Double -> PromoteDiv Int Double
divWiden2 = Double -> Double
Double -> PromoteDiv Int Double
forall a. a -> a
id
instance DivWidenOp Double Int32 where divWiden1 :: Double -> PromoteDiv Double Int32
divWiden1 = Double -> Double
Double -> PromoteDiv Double Int32
forall a. a -> a
id; divWiden2 :: Int32 -> PromoteDiv Double Int32
divWiden2 = Int32 -> Double
Int32 -> PromoteDiv Double Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int32 Double where divWiden1 :: Int32 -> PromoteDiv Int32 Double
divWiden1 = Int32 -> Double
Int32 -> PromoteDiv Int32 Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Double -> PromoteDiv Int32 Double
divWiden2 = Double -> Double
Double -> PromoteDiv Int32 Double
forall a. a -> a
id
instance DivWidenOp Double Int64 where divWiden1 :: Double -> PromoteDiv Double Int64
divWiden1 = Double -> Double
Double -> PromoteDiv Double Int64
forall a. a -> a
id; divWiden2 :: Int64 -> PromoteDiv Double Int64
divWiden2 = Int64 -> Double
Int64 -> PromoteDiv Double Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int64 Double where divWiden1 :: Int64 -> PromoteDiv Int64 Double
divWiden1 = Int64 -> Double
Int64 -> PromoteDiv Int64 Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Double -> PromoteDiv Int64 Double
divWiden2 = Double -> Double
Double -> PromoteDiv Int64 Double
forall a. a -> a
id


instance DivWidenOp Float Int where divWiden1 :: Float -> PromoteDiv Float Int
divWiden1 = Float -> Float
Float -> PromoteDiv Float Int
forall a. a -> a
id; divWiden2 :: Int -> PromoteDiv Float Int
divWiden2 = Int -> Float
Int -> PromoteDiv Float Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int Float where divWiden1 :: Int -> PromoteDiv Int Float
divWiden1 = Int -> Float
Int -> PromoteDiv Int Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Float -> PromoteDiv Int Float
divWiden2 = Float -> Float
Float -> PromoteDiv Int Float
forall a. a -> a
id
instance DivWidenOp Float Int32 where divWiden1 :: Float -> PromoteDiv Float Int32
divWiden1 = Float -> Float
Float -> PromoteDiv Float Int32
forall a. a -> a
id; divWiden2 :: Int32 -> PromoteDiv Float Int32
divWiden2 = Int32 -> Float
Int32 -> PromoteDiv Float Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int32 Float where divWiden1 :: Int32 -> PromoteDiv Int32 Float
divWiden1 = Int32 -> Float
Int32 -> PromoteDiv Int32 Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Float -> PromoteDiv Int32 Float
divWiden2 = Float -> Float
Float -> PromoteDiv Int32 Float
forall a. a -> a
id
instance DivWidenOp Float Int64 where divWiden1 :: Float -> PromoteDiv Float Int64
divWiden1 = Float -> Float
Float -> PromoteDiv Float Int64
forall a. a -> a
id; divWiden2 :: Int64 -> PromoteDiv Float Int64
divWiden2 = Int64 -> Float
Int64 -> PromoteDiv Float Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int64 Float where divWiden1 :: Int64 -> PromoteDiv Int64 Float
divWiden1 = Int64 -> Float
Int64 -> PromoteDiv Int64 Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral; divWiden2 :: Float -> PromoteDiv Int64 Float
divWiden2 = Float -> Float
Float -> PromoteDiv Int64 Float
forall a. a -> a
id


instance DivWidenOp Int Int where
    divWiden1 :: Int -> PromoteDiv Int Int
divWiden1 = Int -> Double
Int -> PromoteDiv Int Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int -> PromoteDiv Int Int
divWiden2 = Int -> Double
Int -> PromoteDiv Int Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int32 Int32 where
    divWiden1 :: Int32 -> PromoteDiv Int32 Int32
divWiden1 = Int32 -> Double
Int32 -> PromoteDiv Int32 Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int32 -> PromoteDiv Int32 Int32
divWiden2 = Int32 -> Double
Int32 -> PromoteDiv Int32 Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int64 Int64 where
    divWiden1 :: Int64 -> PromoteDiv Int64 Int64
divWiden1 = Int64 -> Double
Int64 -> PromoteDiv Int64 Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int64 -> PromoteDiv Int64 Int64
divWiden2 = Int64 -> Double
Int64 -> PromoteDiv Int64 Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int Int32 where
    divWiden1 :: Int -> PromoteDiv Int Int32
divWiden1 = Int -> Double
Int -> PromoteDiv Int Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int32 -> PromoteDiv Int Int32
divWiden2 = Int32 -> Double
Int32 -> PromoteDiv Int Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int32 Int where
    divWiden1 :: Int32 -> PromoteDiv Int32 Int
divWiden1 = Int32 -> Double
Int32 -> PromoteDiv Int32 Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int -> PromoteDiv Int32 Int
divWiden2 = Int -> Double
Int -> PromoteDiv Int32 Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int Int64 where
    divWiden1 :: Int -> PromoteDiv Int Int64
divWiden1 = Int -> Double
Int -> PromoteDiv Int Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int64 -> PromoteDiv Int Int64
divWiden2 = Int64 -> Double
Int64 -> PromoteDiv Int Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int64 Int where
    divWiden1 :: Int64 -> PromoteDiv Int64 Int
divWiden1 = Int64 -> Double
Int64 -> PromoteDiv Int64 Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int -> PromoteDiv Int64 Int
divWiden2 = Int -> Double
Int -> PromoteDiv Int64 Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int32 Int64 where
    divWiden1 :: Int32 -> PromoteDiv Int32 Int64
divWiden1 = Int32 -> Double
Int32 -> PromoteDiv Int32 Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int64 -> PromoteDiv Int32 Int64
divWiden2 = Int64 -> Double
Int64 -> PromoteDiv Int32 Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral
instance DivWidenOp Int64 Int32 where
    divWiden1 :: Int64 -> PromoteDiv Int64 Int32
divWiden1 = Int64 -> Double
Int64 -> PromoteDiv Int64 Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral
    divWiden2 :: Int32 -> PromoteDiv Int64 Int32
divWiden2 = Int32 -> Double
Int32 -> PromoteDiv Int64 Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral


divArithOp ::
    forall a b.
    (DivWidenOp a b) =>
    (PromoteDiv a b -> PromoteDiv a b -> PromoteDiv a b) ->
    a ->
    b ->
    PromoteDiv a b
divArithOp :: forall a b.
DivWidenOp a b =>
(PromoteDiv a b -> PromoteDiv a b -> PromoteDiv a b)
-> a -> b -> PromoteDiv a b
divArithOp PromoteDiv a b -> PromoteDiv a b -> PromoteDiv a b
f a
x b
y = PromoteDiv a b -> PromoteDiv a b -> PromoteDiv a b
f (forall a b. DivWidenOp a b => a -> PromoteDiv a b
divWiden1 @a @b a
x) (forall a b. DivWidenOp a b => b -> PromoteDiv a b
divWiden2 @a @b b
y)


type WidenResultDiv a b =
    NullLift2Result a b (PromoteDiv (BaseType a) (BaseType b))