{-# LANGUAGE ConstraintKinds, CPP, DataKinds, FlexibleContexts,
             FlexibleInstances, KindSignatures, MultiParamTypeClasses,
             PolyKinds, ScopedTypeVariables, TypeFamilies,
             TypeOperators, UndecidableInstances, TemplateHaskell,
             QuasiQuotes, Rank2Types, TypeApplications,
             AllowAmbiguousTypes #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Frames.ExtraInstances where

import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divisible
import Data.Discrimination.Grouping
import Data.Hashable
import Control.DeepSeq
import Frames.Col
import Frames.Rec
import Frames.Frame
import Frames.RecF (AllCols)
import Data.Vinyl.Functor as VF
import Data.Vinyl
import Data.Text (Text)

-- Grouping instances
instance (AllCols Grouping rs
         , Grouping (Record rs)
         , Grouping (ElField (s :-> r))
         , Grouping r
         ) =>
         Grouping (Record ((s :-> r) : rs)) where
  grouping :: Group (Record ((s :-> r) : rs))
grouping = forall (f :: * -> *) a b c.
Divisible f =>
(a -> (b, c)) -> f b -> f c -> f a
divide forall (s :: Symbol) a (rs :: [(Symbol, *)]).
Record ((s :-> a) : rs) -> (a, Record rs)
recUncons forall a. Grouping a => Group a
grouping forall a. Grouping a => Group a
grouping

instance Grouping (Record '[]) where
  grouping :: Group (Record '[])
grouping = forall (f :: * -> *) a. Divisible f => f a
conquer

instance (Grouping a) => Grouping (ElField (s :-> a)) where
   grouping :: Group (ElField (s :-> a))
grouping = forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap forall (s :: Symbol) t. ElField '(s, t) -> t
getCol forall a. Grouping a => Group a
grouping

instance Grouping Text where
  grouping :: Group Text
grouping = forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap forall a. Hashable a => a -> Int
hash forall a. Grouping a => Group a
grouping


-- NFData* instances
#if MIN_VERSION_deepseq(1,4,3)
instance (NFData a) =>
         NFData (VF.Identity a) where
  rnf :: Identity a -> ()
rnf = forall (f :: * -> *) a. (NFData1 f, NFData a) => f a -> ()
rnf1

instance NFData1 VF.Identity where
  liftRnf :: forall a. (a -> ()) -> Identity a -> ()
liftRnf a -> ()
r = a -> ()
r forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Identity a -> a
getIdentity

#if MIN_VERSION_vinyl(0,13,1)
#else
instance (NFData (f r), NFData (Rec f rs)) => NFData (Rec f (r ': rs)) where
  rnf (x :& xs) = rnf x `seq` rnf xs
#endif

instance NFData (Rec f '[]) where
  rnf :: Rec f '[] -> ()
rnf Rec f '[]
RNil = ()

instance (NFData1 f, NFData1 g) => NFData1 (Compose f g) where
  liftRnf :: forall a. (a -> ()) -> Compose f g a -> ()
liftRnf a -> ()
f = forall (f :: * -> *) a. NFData1 f => (a -> ()) -> f a -> ()
liftRnf (forall (f :: * -> *) a. NFData1 f => (a -> ()) -> f a -> ()
liftRnf a -> ()
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l k (f :: l -> *) (g :: k -> l) (x :: k).
Compose f g x -> f (g x)
getCompose

instance NFData (f (g a)) => NFData (Compose f g a) where
  rnf :: Compose f g a -> ()
rnf (Compose f (g a)
x) = forall a. NFData a => a -> ()
rnf f (g a)
x

#endif


instance (NFData a) =>
         NFData (Frame a) where
  rnf :: Frame a -> ()
rnf = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
x ()
acc -> forall a. NFData a => a -> ()
rnf a
x seq :: forall a b. a -> b -> b
`seq` ()
acc) ()

instance (NFData a) => NFData (ElField (s :-> a)) where
  rnf :: ElField (s :-> a) -> ()
rnf = forall a. NFData a => a -> ()
rnf forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (s :: Symbol) t. ElField '(s, t) -> t
getCol