{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module DataFrame.Operations.Typing where
import qualified Data.Text as T
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import Data.Either
import Data.Maybe
import Data.Time
import Data.Type.Equality (TestEquality (..), type (:~:) (Refl))
import DataFrame.Internal.Column (Column (..))
import DataFrame.Internal.DataFrame (DataFrame (..))
import DataFrame.Internal.Parsing
import Type.Reflection (typeRep)
parseDefaults :: Int -> Bool -> String -> DataFrame -> DataFrame
parseDefaults :: Int -> Bool -> String -> DataFrame -> DataFrame
parseDefaults Int
n Bool
safeRead String
dateFormat DataFrame
df = DataFrame
df{columns = V.map (parseDefault n safeRead dateFormat) (columns df)}
parseDefault :: Int -> Bool -> String -> Column -> Column
parseDefault :: Int -> Bool -> String -> Column -> Column
parseDefault Int
n Bool
safeRead String
dateFormat (BoxedColumn (Vector a
c :: V.Vector a)) =
    case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep Text -> Maybe (a :~: Text)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) of
        Maybe (a :~: Text)
Nothing -> case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep String -> Maybe (a :~: String)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @String) of
            Just a :~: String
Refl -> Int -> String -> Bool -> Vector Text -> Column
parseFromExamples Int
n String
dateFormat Bool
safeRead ((String -> Text) -> Vector String -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map String -> Text
T.pack Vector a
Vector String
c)
            Maybe (a :~: String)
Nothing -> Vector a -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector a
c
        Just a :~: Text
Refl -> Int -> String -> Bool -> Vector Text -> Column
parseFromExamples Int
n String
dateFormat Bool
safeRead Vector a
Vector Text
c
parseDefault Int
n Bool
safeRead String
dateFormat (OptionalColumn (Vector (Maybe a)
c :: V.Vector (Maybe a))) =
    case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep Text -> Maybe (a :~: Text)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) of
        Maybe (a :~: Text)
Nothing -> case (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) TypeRep a -> TypeRep String -> Maybe (a :~: String)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
`testEquality` (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @String) of
            Just a :~: String
Refl -> Int -> String -> Bool -> Vector Text -> Column
parseFromExamples Int
n String
dateFormat Bool
safeRead ((Maybe String -> Text) -> Vector (Maybe String) -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map (String -> Text
T.pack (String -> Text)
-> (Maybe String -> String) -> Maybe String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"") Vector (Maybe a)
Vector (Maybe String)
c)
            Maybe (a :~: String)
Nothing -> Vector (Maybe a) -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector (Maybe a)
c
        Just a :~: Text
Refl -> Int -> String -> Bool -> Vector Text -> Column
parseFromExamples Int
n String
dateFormat Bool
safeRead ((Maybe Text -> Text) -> Vector (Maybe Text) -> Vector Text
forall a b. (a -> b) -> Vector a -> Vector b
V.map (Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"") Vector (Maybe a)
Vector (Maybe Text)
c)
parseDefault Int
_ Bool
_ String
_ Column
column = Column
column
parseFromExamples :: Int -> String -> Bool -> V.Vector T.Text -> Column
parseFromExamples :: Int -> String -> Bool -> Vector Text -> Column
parseFromExamples Int
n String
dateFormat Bool
safeRead Vector Text
c
    | (Maybe Int -> Bool) -> Vector (Maybe Int) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Maybe Int -> Bool
forall a. Maybe a -> Bool
isJust ((Text -> Maybe Int) -> Vector Text -> Vector (Maybe Int)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Maybe Int
Text -> Maybe Int
readInt Vector Text
examples)
        Bool -> Bool -> Bool
&& Vector (Maybe Int) -> Vector (Maybe Double) -> Bool
forall a b. Vector (Maybe a) -> Vector (Maybe b) -> Bool
equalNonEmpty ((Text -> Maybe Int) -> Vector Text -> Vector (Maybe Int)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Maybe Int
Text -> Maybe Int
readInt Vector Text
examples) ((Text -> Maybe Double) -> Vector Text -> Vector (Maybe Double)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble Vector Text
examples) =
        let safeVector :: Vector (Either Text Int)
safeVector = (Text -> Either Text Int)
-> Vector Text -> Vector (Either Text Int)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Either Text Int
Text -> Either Text Int
readIntEither Vector Text
c
            notAllParsed :: Bool
notAllParsed = (Either Text Int -> Bool) -> Vector (Either Text Int) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Either Text Int -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Int)
safeVector
         in if Bool
safeRead Bool -> Bool -> Bool
&& Bool
notAllParsed
                then
                    if (Either Text Int -> Bool) -> Vector (Either Text Int) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.all ((Text -> Bool) -> (Int -> Bool) -> Either Text Int -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Bool
isNullish (Bool -> Int -> Bool
forall a b. a -> b -> a
const Bool
False)) ((Either Text Int -> Bool)
-> Vector (Either Text Int) -> Vector (Either Text Int)
forall a. (a -> Bool) -> Vector a -> Vector a
V.filter Either Text Int -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Int)
safeVector)
                        then Vector (Maybe Int) -> Column
forall a. Columnable a => Vector (Maybe a) -> Column
OptionalColumn ((Either Text Int -> Maybe Int)
-> Vector (Either Text Int) -> Vector (Maybe Int)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Int)
-> (Int -> Maybe Int) -> Either Text Int -> Maybe Int
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Int -> Text -> Maybe Int
forall a b. a -> b -> a
const Maybe Int
forall a. Maybe a
Nothing) Int -> Maybe Int
forall a. a -> Maybe a
Just) Vector (Either Text Int)
safeVector)
                        else Vector (Either Text Int) -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector (Either Text Int)
safeVector
                else
                    Vector Int -> Column
forall a. (Columnable a, Unbox a) => Vector a -> Column
UnboxedColumn
                        (Int -> (Int -> Int) -> Vector Int
forall a. Unbox a => Int -> (Int -> a) -> Vector a
VU.generate (Vector Text -> Int
forall a. Vector a -> Int
V.length Vector Text
c) ((Text -> Int) -> (Int -> Int) -> Either Text Int -> Int
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Int
forall a. HasCallStack => a
undefined Int -> Int
forall a. a -> a
id (Either Text Int -> Int) -> (Int -> Either Text Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector (Either Text Int)
safeVector Vector (Either Text Int) -> Int -> Either Text Int
forall a. Vector a -> Int -> a
V.!)))
    | (Maybe Double -> Bool) -> Vector (Maybe Double) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Maybe Double -> Bool
forall a. Maybe a -> Bool
isJust ((Text -> Maybe Double) -> Vector Text -> Vector (Maybe Double)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Maybe Double
Text -> Maybe Double
readDouble Vector Text
examples) =
        let safeVector :: Vector (Either Text Double)
safeVector = (Text -> Either Text Double)
-> Vector Text -> Vector (Either Text Double)
forall a b. (a -> b) -> Vector a -> Vector b
V.map HasCallStack => Text -> Either Text Double
Text -> Either Text Double
readDoubleEither Vector Text
c
            notAllParsed :: Bool
notAllParsed = (Either Text Double -> Bool) -> Vector (Either Text Double) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Either Text Double -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Double)
safeVector
         in if Bool
safeRead Bool -> Bool -> Bool
&& Bool
notAllParsed
                then
                    if (Either Text Double -> Bool) -> Vector (Either Text Double) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.all ((Text -> Bool) -> (Double -> Bool) -> Either Text Double -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Bool
isNullish (Bool -> Double -> Bool
forall a b. a -> b -> a
const Bool
False)) ((Either Text Double -> Bool)
-> Vector (Either Text Double) -> Vector (Either Text Double)
forall a. (a -> Bool) -> Vector a -> Vector a
V.filter Either Text Double -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Double)
safeVector)
                        then Vector (Maybe Double) -> Column
forall a. Columnable a => Vector (Maybe a) -> Column
OptionalColumn ((Either Text Double -> Maybe Double)
-> Vector (Either Text Double) -> Vector (Maybe Double)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Maybe Double)
-> (Double -> Maybe Double) -> Either Text Double -> Maybe Double
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe Double -> Text -> Maybe Double
forall a b. a -> b -> a
const Maybe Double
forall a. Maybe a
Nothing) Double -> Maybe Double
forall a. a -> Maybe a
Just) Vector (Either Text Double)
safeVector)
                        else Vector (Either Text Double) -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector (Either Text Double)
safeVector
                else
                    Vector Double -> Column
forall a. (Columnable a, Unbox a) => Vector a -> Column
UnboxedColumn
                        (Int -> (Int -> Double) -> Vector Double
forall a. Unbox a => Int -> (Int -> a) -> Vector a
VU.generate (Vector Text -> Int
forall a. Vector a -> Int
V.length Vector Text
c) ((Text -> Double)
-> (Double -> Double) -> Either Text Double -> Double
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Double
forall a. HasCallStack => a
undefined Double -> Double
forall a. a -> a
id (Either Text Double -> Double)
-> (Int -> Either Text Double) -> Int -> Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector (Either Text Double)
safeVector Vector (Either Text Double) -> Int -> Either Text Double
forall a. Vector a -> Int -> a
V.!)))
    | (Maybe Day -> Bool) -> Vector (Maybe Day) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Maybe Day -> Bool
forall a. Maybe a -> Bool
isJust ((Text -> Maybe Day) -> Vector Text -> Vector (Maybe Day)
forall a b. (a -> b) -> Vector a -> Vector b
V.map (String -> Text -> Maybe Day
parseTimeOpt String
dateFormat) Vector Text
examples) =
        let
            
            emptyToNothing' :: Text -> Either Text Text
emptyToNothing' Text
v = if Text -> Bool
isNullish Text
v then Text -> Either Text Text
forall a b. a -> Either a b
Left Text
v else Text -> Either Text Text
forall a b. b -> Either a b
Right Text
v
            parseTimeEither :: Text -> Either Text Day
parseTimeEither Text
v = case String -> Text -> Maybe Day
parseTimeOpt String
dateFormat Text
v of
                Just Day
v' -> Day -> Either Text Day
forall a b. b -> Either a b
Right Day
v'
                Maybe Day
Nothing -> Text -> Either Text Day
forall a b. a -> Either a b
Left Text
v
            safeVector :: Vector (Either Text Day)
safeVector = (Text -> Either Text Day)
-> Vector Text -> Vector (Either Text Day)
forall a b. (a -> b) -> Vector a -> Vector b
V.map ((Text -> Either Text Day) -> Either Text Text -> Either Text Day
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
(=<<) Text -> Either Text Day
parseTimeEither (Either Text Text -> Either Text Day)
-> (Text -> Either Text Text) -> Text -> Either Text Day
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text Text
emptyToNothing') Vector Text
c
            toMaybe :: Either a a -> Maybe a
toMaybe (Left a
_) = Maybe a
forall a. Maybe a
Nothing
            toMaybe (Right a
value) = a -> Maybe a
forall a. a -> Maybe a
Just a
value
            lefts :: Vector (Either Text Day)
lefts = (Either Text Day -> Bool)
-> Vector (Either Text Day) -> Vector (Either Text Day)
forall a. (a -> Bool) -> Vector a -> Vector a
V.filter Either Text Day -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Day)
safeVector
            onlyNulls :: Bool
onlyNulls = (Bool -> Bool
not (Vector (Either Text Day) -> Bool
forall a. Vector a -> Bool
V.null Vector (Either Text Day)
lefts) Bool -> Bool -> Bool
&& (Either Text Day -> Bool) -> Vector (Either Text Day) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.all (Text -> Bool
isNullish (Text -> Bool)
-> (Either Text Day -> Text) -> Either Text Day -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either Text Day -> Text
forall a b. a -> Either a b -> a
fromLeft Text
"non-null") Vector (Either Text Day)
lefts)
         in
            if Bool
safeRead
                then
                    if Bool
onlyNulls
                        then Vector (Maybe Day) -> Column
forall a. Columnable a => Vector (Maybe a) -> Column
OptionalColumn ((Either Text Day -> Maybe Day)
-> Vector (Either Text Day) -> Vector (Maybe Day)
forall a b. (a -> b) -> Vector a -> Vector b
V.map Either Text Day -> Maybe Day
forall {a} {a}. Either a a -> Maybe a
toMaybe Vector (Either Text Day)
safeVector)
                        else
                            if (Either Text Day -> Bool) -> Vector (Either Text Day) -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Either Text Day -> Bool
forall a b. Either a b -> Bool
isLeft Vector (Either Text Day)
safeVector
                                then Vector (Either Text Day) -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector (Either Text Day)
safeVector
                                else Vector Day -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn ((Text -> Day) -> Vector Text -> Vector Day
forall a b. (a -> b) -> Vector a -> Vector b
V.map (String -> Text -> Day
unsafeParseTime String
dateFormat) Vector Text
c)
                else Vector Day -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn ((Text -> Day) -> Vector Text -> Vector Day
forall a b. (a -> b) -> Vector a -> Vector b
V.map (String -> Text -> Day
unsafeParseTime String
dateFormat) Vector Text
c)
    | Bool
otherwise =
        let
            safeVector :: Vector (Maybe Text)
safeVector = (Text -> Maybe Text) -> Vector Text -> Vector (Maybe Text)
forall a b. (a -> b) -> Vector a -> Vector b
V.map Text -> Maybe Text
emptyToNothing Vector Text
c
            hasNulls :: Bool
hasNulls = (Text -> Bool) -> Vector Text -> Bool
forall a. (a -> Bool) -> Vector a -> Bool
V.any Text -> Bool
isNullish Vector Text
c
         in
            if Bool
safeRead Bool -> Bool -> Bool
&& Bool
hasNulls then Vector (Maybe Text) -> Column
forall a. Columnable a => Vector (Maybe a) -> Column
OptionalColumn Vector (Maybe Text)
safeVector else Vector Text -> Column
forall a. Columnable a => Vector a -> Column
BoxedColumn Vector Text
c
  where
    examples :: Vector Text
examples = Int -> Vector Text -> Vector Text
forall a. Int -> Vector a -> Vector a
V.take Int
n Vector Text
c
emptyToNothing :: T.Text -> Maybe T.Text
emptyToNothing :: Text -> Maybe Text
emptyToNothing Text
v = if Text -> Bool
isNullish Text
v then Maybe Text
forall a. Maybe a
Nothing else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
v
parseTimeOpt :: String -> T.Text -> Maybe Day
parseTimeOpt :: String -> Text -> Maybe Day
parseTimeOpt String
dateFormat Text
s =
    Bool -> TimeLocale -> String -> String -> Maybe Day
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
parseTimeM 
        Bool
True
        TimeLocale
defaultTimeLocale
        String
dateFormat
        (Text -> String
T.unpack Text
s)
unsafeParseTime :: String -> T.Text -> Day
unsafeParseTime :: String -> Text -> Day
unsafeParseTime String
dateFormat Text
s =
    Bool -> TimeLocale -> String -> String -> Day
forall t.
ParseTime t =>
Bool -> TimeLocale -> String -> String -> t
parseTimeOrError 
        Bool
True
        TimeLocale
defaultTimeLocale
        String
dateFormat
        (Text -> String
T.unpack Text
s)
countNonEmpty :: V.Vector (Maybe a) -> Int
countNonEmpty :: forall a. Vector (Maybe a) -> Int
countNonEmpty Vector (Maybe a)
xs = Vector (Maybe a) -> Int
forall a. Vector a -> Int
V.length ((Maybe a -> Bool) -> Vector (Maybe a) -> Vector (Maybe a)
forall a. (a -> Bool) -> Vector a -> Vector a
V.filter Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Vector (Maybe a)
xs)
equalNonEmpty :: V.Vector (Maybe a) -> V.Vector (Maybe b) -> Bool
equalNonEmpty :: forall a b. Vector (Maybe a) -> Vector (Maybe b) -> Bool
equalNonEmpty Vector (Maybe a)
xs Vector (Maybe b)
ys = Vector (Maybe a) -> Int
forall a. Vector (Maybe a) -> Int
countNonEmpty Vector (Maybe a)
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Vector (Maybe b) -> Int
forall a. Vector (Maybe a) -> Int
countNonEmpty Vector (Maybe b)
ys