packages feed

dataframe-1.0.0.0: tests/Operations/Nullable.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Operations.Nullable where

import qualified Data.Vector as V
import qualified DataFrame as D
import qualified DataFrame.Functions as F
import qualified DataFrame.Internal.Column as DI
import qualified DataFrame.Internal.DataFrame as DI
import DataFrame.Internal.Expression (Expr)
import DataFrame.Operators ((.*), (.+), (.-), (./), (.==))
import qualified DataFrame.Typed as DT
import qualified DataFrame.Typed.Expr as TE
import DataFrame.Typed.Types (TExpr (..))

import Test.HUnit

-- ---------------------------------------------------------------------------
-- Untyped Expr layer tests
-- ---------------------------------------------------------------------------

-- DataFrame with one plain Int column and one Maybe Int column
testData :: D.DataFrame
testData =
    D.fromNamedColumns
        [ ("x", DI.fromList ([1, 2, 3] :: [Int]))
        , ("y", DI.OptionalColumn (V.fromList [Just 10, Nothing, Just 30 :: Maybe Int]))
        ]

-- | col @Int .+ col @(Maybe Int)  should give Maybe Int column
addIntMaybeInt :: Test
addIntMaybeInt =
    TestCase
        ( assertEqual
            "Int .+ Maybe Int = Maybe Int"
            (Just $ DI.OptionalColumn (V.fromList [Just 11, Nothing, Just 33 :: Maybe Int]))
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @Int "x" .+ F.col @(Maybe Int) "y")
                    testData
            )
        )

-- | col @(Maybe Int) .+ col @Int  should give Maybe Int column
addMaybeIntInt :: Test
addMaybeIntInt =
    TestCase
        ( assertEqual
            "Maybe Int .+ Int = Maybe Int"
            (Just $ DI.OptionalColumn (V.fromList [Just 11, Nothing, Just 33 :: Maybe Int]))
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @(Maybe Int) "y" .+ F.col @Int "x")
                    testData
            )
        )

-- | col @Int .+ col @Int  (same-type non-nullable) should give Int column
addIntInt :: Test
addIntInt =
    TestCase
        ( assertEqual
            "Int .+ Int = Int (non-nullable preserved)"
            (Just $ DI.fromList [2, 4, 6 :: Int])
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @Int "x" .+ F.col @Int "x")
                    testData
            )
        )

-- | col @(Maybe Int) .+ col @(Maybe Int)  should give Maybe Int column
addMaybeMaybe :: Test
addMaybeMaybe =
    TestCase
        ( assertEqual
            "Maybe Int .+ Maybe Int = Maybe Int"
            (Just $ DI.OptionalColumn (V.fromList [Just 20, Nothing, Just 60 :: Maybe Int]))
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @(Maybe Int) "y" .+ F.col @(Maybe Int) "y")
                    testData
            )
        )

-- | Subtraction: Int .- Maybe Int
subIntMaybeInt :: Test
subIntMaybeInt =
    TestCase
        ( assertEqual
            "Int .- Maybe Int = Maybe Int"
            ( Just $
                DI.OptionalColumn (V.fromList [Just (-9), Nothing, Just (-27) :: Maybe Int])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @Int "x" .- F.col @(Maybe Int) "y")
                    testData
            )
        )

-- | Comparison: Int .== Maybe Int gives Maybe Bool
eqIntMaybeInt :: Test
eqIntMaybeInt =
    TestCase
        ( assertEqual
            "Int .== Maybe Int = Maybe Bool"
            ( Just $
                DI.OptionalColumn (V.fromList [Just False, Nothing, Just False :: Maybe Bool])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @Int "x" .== F.col @(Maybe Int) "y" :: Expr (Maybe Bool))
                    testData
            )
        )

-- | Comparison: Int .== Int  gives plain Bool (backwards compatible)
eqIntInt :: Test
eqIntInt =
    TestCase
        ( assertEqual
            "Int .== Int = Bool (non-nullable, backwards compatible)"
            (Just $ DI.fromList [True, False, False :: Bool])
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @Int "x" .== F.lit (1 :: Int) :: Expr Bool)
                    testData
            )
        )

-- ---------------------------------------------------------------------------
-- nullLift / nullLift2 — untyped layer
-- ---------------------------------------------------------------------------

-- | nullLift negate on Maybe Int propagates Nothing
nullLiftMaybeInt :: Test
nullLiftMaybeInt =
    TestCase
        ( assertEqual
            "nullLift negate (Maybe Int) propagates Nothing"
            ( Just $
                DI.OptionalColumn (V.fromList [Just (-10), Nothing, Just (-30) :: Maybe Int])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.nullLift negate (F.col @(Maybe Int) "y") :: Expr (Maybe Int))
                    testData
            )
        )

-- | nullLift negate on plain Int — no Nothing, plain result
nullLiftInt :: Test
nullLiftInt =
    TestCase
        ( assertEqual
            "nullLift negate (Int) gives Int column"
            (Just $ DI.fromList [-1, -2, -3 :: Int])
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.nullLift negate (F.col @Int "x") :: Expr Int)
                    testData
            )
        )

-- | nullLift2 (+) Int (Maybe Int) → Maybe Int
nullLift2IntMaybeInt :: Test
nullLift2IntMaybeInt =
    TestCase
        ( assertEqual
            "nullLift2 (+) Int (Maybe Int) = Maybe Int"
            (Just $ DI.OptionalColumn (V.fromList [Just 11, Nothing, Just 33 :: Maybe Int]))
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.nullLift2 (+) (F.col @Int "x") (F.col @(Maybe Int) "y") :: Expr (Maybe Int))
                    testData
            )
        )

-- | nullLift2 (+) (Maybe Int) Int → Maybe Int
nullLift2MaybeIntInt :: Test
nullLift2MaybeIntInt =
    TestCase
        ( assertEqual
            "nullLift2 (+) (Maybe Int) Int = Maybe Int"
            (Just $ DI.OptionalColumn (V.fromList [Just 11, Nothing, Just 33 :: Maybe Int]))
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.nullLift2 (+) (F.col @(Maybe Int) "y") (F.col @Int "x") :: Expr (Maybe Int))
                    testData
            )
        )

-- | nullLift2 (+) Int Int → plain Int
nullLift2IntInt :: Test
nullLift2IntInt =
    TestCase
        ( assertEqual
            "nullLift2 (+) Int Int = Int (non-nullable)"
            (Just $ DI.fromList [2, 4, 6 :: Int])
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.nullLift2 (+) (F.col @Int "x") (F.col @Int "x") :: Expr Int)
                    testData
            )
        )

-- ---------------------------------------------------------------------------
-- Cross-type arithmetic (Int × Double promotion)
-- ---------------------------------------------------------------------------

-- DataFrame with Int, Maybe Int, Double, Maybe Double columns
crossData :: D.DataFrame
crossData =
    D.fromNamedColumns
        [ ("x", DI.fromList ([1, 2, 3] :: [Int]))
        , ("y", DI.OptionalColumn (V.fromList [Just 10, Nothing, Just 30 :: Maybe Int]))
        , ("d", DI.fromList ([1.5, 2.5, 3.5] :: [Double]))
        ,
            ( "md"
            , DI.OptionalColumn (V.fromList [Just 10.5, Nothing, Just 30.5 :: Maybe Double])
            )
        ]

-- | col @Int .+ col @Double → Double
addIntDouble :: Test
addIntDouble =
    TestCase
        ( assertEqual
            "Int .+ Double = Double"
            (Just $ DI.fromList [2.5, 4.5, 6.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .+ F.col @Double "d") crossData
            )
        )

-- | col @Double .+ col @Int → Double
addDoubleInt :: Test
addDoubleInt =
    TestCase
        ( assertEqual
            "Double .+ Int = Double"
            (Just $ DI.fromList [2.5, 4.5, 6.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Double "d" .+ F.col @Int "x") crossData
            )
        )

-- | col @(Maybe Int) .+ col @Double → Maybe Double
addMaybeIntDouble :: Test
addMaybeIntDouble =
    TestCase
        ( assertEqual
            "Maybe Int .+ Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 11.5, Nothing, Just 33.5 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @(Maybe Int) "y" .+ F.col @Double "d") crossData
            )
        )

-- | col @Int .+ col @(Maybe Double) → Maybe Double
addIntMaybeDouble :: Test
addIntMaybeDouble =
    TestCase
        ( assertEqual
            "Int .+ Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 11.5, Nothing, Just 33.5 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .+ F.col @(Maybe Double) "md") crossData
            )
        )

-- | col @(Maybe Int) .+ col @(Maybe Double) → Maybe Double
addMaybeIntMaybeDouble :: Test
addMaybeIntMaybeDouble =
    TestCase
        ( assertEqual
            "Maybe Int .+ Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 20.5, Nothing, Just 60.5 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @(Maybe Int) "y" .+ F.col @(Maybe Double) "md")
                    crossData
            )
        )

-- | col @Int .- col @Double → Double
subIntDouble :: Test
subIntDouble =
    TestCase
        ( assertEqual
            "Int .- Double = Double"
            (Just $ DI.fromList [-0.5, -0.5, -0.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .- F.col @Double "d") crossData
            )
        )

-- | col @Int .* col @Double → Double
mulIntDouble :: Test
mulIntDouble =
    TestCase
        ( assertEqual
            "Int .* Double = Double"
            (Just $ DI.fromList [1.5, 5.0, 10.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .* F.col @Double "d") crossData
            )
        )

-- | col @Double .- col @Int → Double
subDoubleInt :: Test
subDoubleInt =
    TestCase
        ( assertEqual
            "Double .- Int = Double"
            (Just $ DI.fromList [0.5, 0.5, 0.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Double "d" .- F.col @Int "x") crossData
            )
        )

-- | col @(Maybe Int) .- col @Double → Maybe Double
subMaybeIntDouble :: Test
subMaybeIntDouble =
    TestCase
        ( assertEqual
            "Maybe Int .- Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 8.5, Nothing, Just 26.5 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @(Maybe Int) "y" .- F.col @Double "d") crossData
            )
        )

-- | col @Int .- col @(Maybe Double) → Maybe Double
subIntMaybeDouble :: Test
subIntMaybeDouble =
    TestCase
        ( assertEqual
            "Int .- Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn
                    (V.fromList [Just (-9.5), Nothing, Just (-27.5) :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .- F.col @(Maybe Double) "md") crossData
            )
        )

-- | col @(Maybe Int) .- col @(Maybe Double) → Maybe Double
subMaybeIntMaybeDouble :: Test
subMaybeIntMaybeDouble =
    TestCase
        ( assertEqual
            "Maybe Int .- Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn
                    (V.fromList [Just (-0.5), Nothing, Just (-0.5) :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @(Maybe Int) "y" .- F.col @(Maybe Double) "md")
                    crossData
            )
        )

-- | col @Double .* col @Int → Double
mulDoubleInt :: Test
mulDoubleInt =
    TestCase
        ( assertEqual
            "Double .* Int = Double"
            (Just $ DI.fromList [1.5, 5.0, 10.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Double "d" .* F.col @Int "x") crossData
            )
        )

-- | col @(Maybe Int) .* col @Double → Maybe Double
mulMaybeIntDouble :: Test
mulMaybeIntDouble =
    TestCase
        ( assertEqual
            "Maybe Int .* Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 15.0, Nothing, Just 105.0 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @(Maybe Int) "y" .* F.col @Double "d") crossData
            )
        )

-- | col @Int .* col @(Maybe Double) → Maybe Double
mulIntMaybeDouble :: Test
mulIntMaybeDouble =
    TestCase
        ( assertEqual
            "Int .* Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 10.5, Nothing, Just 91.5 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" .* F.col @(Maybe Double) "md") crossData
            )
        )

-- | col @(Maybe Int) .* col @(Maybe Double) → Maybe Double
mulMaybeIntMaybeDouble :: Test
mulMaybeIntMaybeDouble =
    TestCase
        ( assertEqual
            "Maybe Int .* Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 105.0, Nothing, Just 915.0 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive
                    "result"
                    (F.col @(Maybe Int) "y" .* F.col @(Maybe Double) "md")
                    crossData
            )
        )

-- Division tests use clean-dividing data: x=[2,4,6], d=[1,2,3]
divData :: D.DataFrame
divData =
    D.fromNamedColumns
        [ ("x", DI.fromList ([2, 4, 6] :: [Int]))
        , ("y", DI.OptionalColumn (V.fromList [Just 4, Nothing, Just 6 :: Maybe Int]))
        , ("d", DI.fromList ([1.0, 2.0, 3.0] :: [Double]))
        ,
            ( "md"
            , DI.OptionalColumn (V.fromList [Just 1.0, Nothing, Just 3.0 :: Maybe Double])
            )
        ]

-- | col @Int ./ col @Double → Double
divIntDouble :: Test
divIntDouble =
    TestCase
        ( assertEqual
            "Int ./ Double = Double"
            (Just $ DI.fromList [2.0, 2.0, 2.0 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" ./ F.col @Double "d") divData
            )
        )

-- | col @Double ./ col @Int → Double
divDoubleInt :: Test
divDoubleInt =
    TestCase
        ( assertEqual
            "Double ./ Int = Double"
            (Just $ DI.fromList [0.5, 0.5, 0.5 :: Double])
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Double "d" ./ F.col @Int "x") divData
            )
        )

-- | col @(Maybe Int) ./ col @Double → Maybe Double
divMaybeIntDouble :: Test
divMaybeIntDouble =
    TestCase
        ( assertEqual
            "Maybe Int ./ Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 4.0, Nothing, Just 2.0 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @(Maybe Int) "y" ./ F.col @Double "d") divData
            )
        )

-- | col @Int ./ col @(Maybe Double) → Maybe Double
divIntMaybeDouble :: Test
divIntMaybeDouble =
    TestCase
        ( assertEqual
            "Int ./ Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 2.0, Nothing, Just 2.0 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @Int "x" ./ F.col @(Maybe Double) "md") divData
            )
        )

-- | col @(Maybe Int) ./ col @(Maybe Double) → Maybe Double
divMaybeIntMaybeDouble :: Test
divMaybeIntMaybeDouble =
    TestCase
        ( assertEqual
            "Maybe Int ./ Maybe Double = Maybe Double"
            ( Just $
                DI.OptionalColumn (V.fromList [Just 4.0, Nothing, Just 2.0 :: Maybe Double])
            )
            ( DI.getColumn "result" $
                D.derive "result" (F.col @(Maybe Int) "y" ./ F.col @(Maybe Double) "md") divData
            )
        )

-- ---------------------------------------------------------------------------
-- Typed TExpr layer — cross-type arithmetic
-- ---------------------------------------------------------------------------

type CrossSchema =
    '[ DT.Column "x" Int
     , DT.Column "y" (Maybe Int)
     , DT.Column "d" Double
     , DT.Column "md" (Maybe Double)
     ]

typedCrossData :: DT.TypedDataFrame CrossSchema
typedCrossData =
    either (error . show) id $
        DT.freezeWithError @CrossSchema crossData

-- | Typed: col @"x" .+ col @"d"  → Double
typedAddIntDouble :: Test
typedAddIntDouble =
    TestCase
        ( assertEqual
            "Typed: Int .+ Double = Double"
            [2.5, 4.5, 6.5 :: Double]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"x" TE..+ TE.col @"d") typedCrossData
            )
        )

-- | Typed: col @"y" .+ col @"d"  → Maybe Double
typedAddMaybeIntDouble :: Test
typedAddMaybeIntDouble =
    TestCase
        ( assertEqual
            "Typed: Maybe Int .+ Double = Maybe Double"
            [Just 11.5, Nothing, Just 33.5]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"y" TE..+ TE.col @"d") typedCrossData
            )
        )

-- | Typed: col @"x" .+ col @"md"  → Maybe Double
typedAddIntMaybeDouble :: Test
typedAddIntMaybeDouble =
    TestCase
        ( assertEqual
            "Typed: Int .+ Maybe Double = Maybe Double"
            [Just 11.5, Nothing, Just 33.5]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"x" TE..+ TE.col @"md") typedCrossData
            )
        )

-- | Typed: col @"y" .+ col @"md"  → Maybe Double
typedAddMaybeIntMaybeDouble :: Test
typedAddMaybeIntMaybeDouble =
    TestCase
        ( assertEqual
            "Typed: Maybe Int .+ Maybe Double = Maybe Double"
            [Just 20.5, Nothing, Just 60.5]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"y" TE..+ TE.col @"md") typedCrossData
            )
        )

-- | Typed: col @"x" .- col @"d"  → Double
typedSubIntDouble :: Test
typedSubIntDouble =
    TestCase
        ( assertEqual
            "Typed: Int .- Double = Double"
            [-0.5, -0.5, -0.5 :: Double]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"x" TE..- TE.col @"d") typedCrossData
            )
        )

-- | Typed: col @"x" .* col @"d"  → Double
typedMulIntDouble :: Test
typedMulIntDouble =
    TestCase
        ( assertEqual
            "Typed: Int .* Double = Double"
            [1.5, 5.0, 10.5 :: Double]
            ( DT.columnAsList @"result" $
                DT.derive @"result" (TE.col @"x" TE..* TE.col @"d") typedCrossData
            )
        )

-- ---------------------------------------------------------------------------
-- Typed TExpr layer tests
-- ---------------------------------------------------------------------------

type TestSchema = '[DT.Column "x" Int, DT.Column "y" (Maybe Int)]

typedTestData :: DT.TypedDataFrame TestSchema
typedTestData =
    either (error . show) id $
        DT.freezeWithError @TestSchema testData

-- | Typed: col @"x" .+ col @"y"  should give Maybe Int column
typedAddIntMaybeInt :: Test
typedAddIntMaybeInt =
    TestCase
        ( assertEqual
            "Typed: Int .+ Maybe Int = Maybe Int"
            [Just 11, Nothing, Just 33]
            ( DT.columnAsList @"result" $
                DT.derive
                    @"result"
                    (TE.col @"x" TE..+ TE.col @"y")
                    typedTestData
            )
        )

-- | Typed: nullLift negate on Maybe Int propagates Nothing
typedNullLiftMaybeInt :: Test
typedNullLiftMaybeInt =
    TestCase
        ( assertEqual
            "Typed nullLift negate (Maybe Int) propagates Nothing"
            [Just (-10), Nothing, Just (-30 :: Int)]
            ( DT.columnAsList @"result" $
                DT.derive
                    @"result"
                    (TE.nullLift negate (TE.col @"y") :: TExpr TestSchema (Maybe Int))
                    typedTestData
            )
        )

-- | Typed: nullLift negate on plain Int
typedNullLiftInt :: Test
typedNullLiftInt =
    TestCase
        ( assertEqual
            "Typed nullLift negate (Int) gives Int column"
            [-1, -2, -3 :: Int]
            ( DT.columnAsList @"result" $
                DT.derive
                    @"result"
                    (TE.nullLift negate (TE.col @"x") :: TExpr TestSchema Int)
                    typedTestData
            )
        )

-- | Typed: nullLift2 (+) col @"x" col @"y" → Maybe Int
typedNullLift2IntMaybeInt :: Test
typedNullLift2IntMaybeInt =
    TestCase
        ( assertEqual
            "Typed nullLift2 (+) Int (Maybe Int) = Maybe Int"
            [Just 11, Nothing, Just 33 :: Maybe Int]
            ( DT.columnAsList @"result" $
                DT.derive
                    @"result"
                    (TE.nullLift2 (+) (TE.col @"x") (TE.col @"y") :: TExpr TestSchema (Maybe Int))
                    typedTestData
            )
        )

-- | Typed: col @"y" .== col @"y"  should give Maybe Bool column
typedEqMaybeMaybe :: Test
typedEqMaybeMaybe =
    TestCase
        ( assertEqual
            "Typed: Maybe Int .== Maybe Int = Maybe Bool"
            [Just True, Nothing, Just True]
            ( DT.columnAsList @"result" $
                DT.derive
                    @"result"
                    (TE.col @"y" TE..== TE.col @"y")
                    typedTestData
            )
        )

-- | apply negate to a Maybe Int column — should fmap over inner values
applyFmapMaybeInt :: Test
applyFmapMaybeInt =
    TestCase
        ( assertEqual
            "apply negate to Maybe Int column fmaps"
            (Just $ DI.OptionalColumn (V.fromList [Just (-10), Nothing, Just (-30 :: Int)]))
            ( DI.getColumn "y" $
                D.apply @Int negate "y" testData
            )
        )

-- | apply to a plain Int column still works
applyPlainInt :: Test
applyPlainInt =
    TestCase
        ( assertEqual
            "apply negate to plain Int column still works"
            (Just $ DI.fromList [-1, -2, -3 :: Int])
            ( DI.getColumn "x" $
                D.apply @Int negate "x" testData
            )
        )

tests :: [Test]
tests =
    [ TestLabel "addIntMaybeInt" addIntMaybeInt
    , TestLabel "addMaybeIntInt" addMaybeIntInt
    , TestLabel "addIntInt" addIntInt
    , TestLabel "addMaybeMaybe" addMaybeMaybe
    , TestLabel "subIntMaybeInt" subIntMaybeInt
    , TestLabel "eqIntMaybeInt" eqIntMaybeInt
    , TestLabel "eqIntInt" eqIntInt
    , TestLabel "nullLiftMaybeInt" nullLiftMaybeInt
    , TestLabel "nullLiftInt" nullLiftInt
    , TestLabel "nullLift2IntMaybeInt" nullLift2IntMaybeInt
    , TestLabel "nullLift2MaybeIntInt" nullLift2MaybeIntInt
    , TestLabel "nullLift2IntInt" nullLift2IntInt
    , TestLabel "typedAddIntMaybeInt" typedAddIntMaybeInt
    , TestLabel "typedEqMaybeMaybe" typedEqMaybeMaybe
    , TestLabel "typedNullLiftMaybeInt" typedNullLiftMaybeInt
    , TestLabel "typedNullLiftInt" typedNullLiftInt
    , TestLabel "typedNullLift2IntMaybeInt" typedNullLift2IntMaybeInt
    , TestLabel "applyFmapMaybeInt" applyFmapMaybeInt
    , TestLabel "applyPlainInt" applyPlainInt
    , TestLabel "addIntDouble" addIntDouble
    , TestLabel "addDoubleInt" addDoubleInt
    , TestLabel "addMaybeIntDouble" addMaybeIntDouble
    , TestLabel "addIntMaybeDouble" addIntMaybeDouble
    , TestLabel "addMaybeIntMaybeDouble" addMaybeIntMaybeDouble
    , TestLabel "subIntDouble" subIntDouble
    , TestLabel "subDoubleInt" subDoubleInt
    , TestLabel "subMaybeIntDouble" subMaybeIntDouble
    , TestLabel "subIntMaybeDouble" subIntMaybeDouble
    , TestLabel "subMaybeIntMaybeDouble" subMaybeIntMaybeDouble
    , TestLabel "mulIntDouble" mulIntDouble
    , TestLabel "mulDoubleInt" mulDoubleInt
    , TestLabel "mulMaybeIntDouble" mulMaybeIntDouble
    , TestLabel "mulIntMaybeDouble" mulIntMaybeDouble
    , TestLabel "mulMaybeIntMaybeDouble" mulMaybeIntMaybeDouble
    , TestLabel "divIntDouble" divIntDouble
    , TestLabel "divDoubleInt" divDoubleInt
    , TestLabel "divMaybeIntDouble" divMaybeIntDouble
    , TestLabel "divIntMaybeDouble" divIntMaybeDouble
    , TestLabel "divMaybeIntMaybeDouble" divMaybeIntMaybeDouble
    , TestLabel "typedAddIntDouble" typedAddIntDouble
    , TestLabel "typedAddMaybeIntDouble" typedAddMaybeIntDouble
    , TestLabel "typedAddIntMaybeDouble" typedAddIntMaybeDouble
    , TestLabel "typedAddMaybeIntMaybeDouble" typedAddMaybeIntMaybeDouble
    , TestLabel "typedSubIntDouble" typedSubIntDouble
    , TestLabel "typedMulIntDouble" typedMulIntDouble
    ]