{-|
Module      : Generate arbitrary Intervals
Description : Functions for generating arbitrary intervals
Copyright   : (c) NoviSci, Inc 2020
License     : BSD3
Maintainer  : bsaul@novisci.com
Stability   : experimental
-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE TypeApplications #-}

module IntervalAlgebra.Arbitrary() where

import Test.QuickCheck      ( Arbitrary(arbitrary, shrink) )
import GHC.Int              ( Int )
import GHC.Num              ( Num((+), negate) )
import Control.Applicative  ( (<$>) )
import Control.Monad        ( liftM2 )
import IntervalAlgebra      (Interval, beginerval)
import Data.Function        ( (.) )
import Data.Time as DT      ( Day(ModifiedJulianDay), toModifiedJulianDay)

instance Arbitrary (Interval Int) where
  arbitrary :: Gen (Interval Int)
arbitrary = (Int -> Int -> Interval Int)
-> Gen Int -> Gen Int -> Gen (Interval Int)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Int -> Int -> Interval Int
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval Gen Int
forall a. Arbitrary a => Gen a
arbitrary Gen Int
forall a. Arbitrary a => Gen a
arbitrary

instance Arbitrary DT.Day where
    arbitrary :: Gen Day
arbitrary = Integer -> Day
DT.ModifiedJulianDay (Integer -> Day) -> (Integer -> Integer) -> Integer -> Day
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer
2000 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+) (Integer -> Day) -> Gen Integer -> Gen Day
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Integer
forall a. Arbitrary a => Gen a
arbitrary
    shrink :: Day -> [Day]
shrink    = (Integer -> Day
DT.ModifiedJulianDay (Integer -> Day) -> [Integer] -> [Day]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([Integer] -> [Day]) -> (Day -> [Integer]) -> Day -> [Day]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> [Integer]
forall a. Arbitrary a => a -> [a]
shrink (Integer -> [Integer]) -> (Day -> Integer) -> Day -> [Integer]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
DT.toModifiedJulianDay

instance Arbitrary (Interval DT.Day) where
  arbitrary :: Gen (Interval Day)
arbitrary = (Integer -> Day -> Interval Day)
-> Gen Integer -> Gen Day -> Gen (Interval Day)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Integer -> Day -> Interval Day
forall a b. IntervalSizeable a b => b -> a -> Interval a
beginerval Gen Integer
forall a. Arbitrary a => Gen a
arbitrary Gen Day
forall a. Arbitrary a => Gen a
arbitrary