{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wall #-}

-- | Typeclass for mimimum and maximum on functors
-- use with
-- import Prelude hiding (minimum, maximum)

module ConCat.MinMax(MinMax(..), MinMaxRep(..)) where

import Prelude hiding (minimum, maximum)
import GHC.TypeLits
import qualified Data.Vector as DataVector
import Data.Vector.Generic.Sized as Vector
import qualified Data.Vector.Generic as VectorGeneric
import Data.Functor.Rep (Representable(..))

class Ord a => MinMax f a where
  minimum :: f a -> a
  maximum :: f a -> a

instance (VectorGeneric.Vector v a, Ord a, n ~ (m + 1)) => MinMax (Vector v n) a where
  minimum :: Vector v n a -> a
minimum = Vector v n a -> a
Vector v (m + 1) a -> a
forall (v :: * -> *) a (n :: Natural).
(Vector v a, Ord a) =>
Vector v (n + 1) a -> a
Vector.minimum
  maximum :: Vector v n a -> a
maximum = Vector v n a -> a
Vector v (m + 1) a -> a
forall (v :: * -> *) a (n :: Natural).
(Vector v a, Ord a) =>
Vector v (n + 1) a -> a
Vector.maximum

class (Ord a, Representable f) => MinMaxRep f a where
  minimumRep :: f a -> (Rep f, a)
  maximumRep :: f a -> (Rep f, a)
  
instance (Ord a, KnownNat n, n ~ (m + 1)) => MinMaxRep (Vector DataVector.Vector n) a where
  minimumRep :: Vector Vector n a -> (Rep (Vector Vector n), a)
minimumRep Vector Vector n a
v =
    let i :: Finite (m + 1)
i = Vector Vector (m + 1) a -> Finite (m + 1)
forall (v :: * -> *) a (n :: Natural).
(Vector v a, Ord a) =>
Vector v (n + 1) a -> Finite (n + 1)
Vector.minIndex Vector Vector n a
Vector Vector (m + 1) a
v
    in (Rep (Vector Vector n)
Finite (m + 1)
i, Vector Vector n a -> Finite n -> a
forall (v :: * -> *) (n :: Natural) a.
Vector v a =>
Vector v n a -> Finite n -> a
Vector.index Vector Vector n a
v Finite n
Finite (m + 1)
i)
  maximumRep :: Vector Vector n a -> (Rep (Vector Vector n), a)
maximumRep Vector Vector n a
v =
    let i :: Finite (m + 1)
i = Vector Vector (m + 1) a -> Finite (m + 1)
forall (v :: * -> *) a (n :: Natural).
(Vector v a, Ord a) =>
Vector v (n + 1) a -> Finite (n + 1)
Vector.maxIndex Vector Vector n a
Vector Vector (m + 1) a
v
    in (Rep (Vector Vector n)
Finite (m + 1)
i, Vector Vector n a -> Finite n -> a
forall (v :: * -> *) (n :: Natural) a.
Vector v a =>
Vector v n a -> Finite n -> a
Vector.index Vector Vector n a
v Finite n
Finite (m + 1)
i)