module Sound.MIDI.Utility where

import qualified Test.QuickCheck as QC
import System.Random (Random(randomR), RandomGen)
import Data.Tuple.HT (mapFst, )
import Data.Word (Word8, )


{-# INLINE checkRange #-}
checkRange :: (Bounded a, Ord a, Show a) =>
   String -> (Int -> a) -> Int -> a
checkRange :: forall a.
(Bounded a, Ord a, Show a) =>
String -> (Int -> a) -> Int -> a
checkRange String
typ Int -> a
f Int
x =
   let y :: a
y = Int -> a
f Int
x
   in  if forall a. Bounded a => a
minBound forall a. Ord a => a -> a -> Bool
<= a
y Bool -> Bool -> Bool
&& a
y forall a. Ord a => a -> a -> Bool
<= forall a. Bounded a => a
maxBound
         then a
y
         else forall a. HasCallStack => String -> a
error (String
typ forall a. [a] -> [a] -> [a]
++ String
": value " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Int
x forall a. [a] -> [a] -> [a]
++ String
" outside range " forall a. [a] -> [a] -> [a]
++
                     forall a. Show a => a -> String
show ((forall a. Bounded a => a
minBound, forall a. Bounded a => a
maxBound) forall a. a -> a -> a
`asTypeOf` (a
y,a
y)))

{-# INLINE loopM #-}
loopM :: Monad m => (a -> Bool) -> m a -> (a -> m ()) -> m a
loopM :: forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> m a -> (a -> m ()) -> m a
loopM a -> Bool
p m a
preExit a -> m ()
postExit =
   let go :: m a
go =
         m a
preExit forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
x ->
            if a -> Bool
p a
x
              then forall (m :: * -> *) a. Monad m => a -> m a
return a
x
              else a -> m ()
postExit a
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m a
go
   in  m a
go




-- random generators

enumRandomR :: (Enum a, RandomGen g) => (a,a) -> g -> (a,g)
enumRandomR :: forall a g. (Enum a, RandomGen g) => (a, a) -> g -> (a, g)
enumRandomR (a
l,a
r) =
   forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst forall a. Enum a => Int -> a
toEnum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (forall a. Enum a => a -> Int
fromEnum a
l, forall a. Enum a => a -> Int
fromEnum a
r)

boundedEnumRandom :: (Enum a, Bounded a, RandomGen g) => g -> (a,g)
boundedEnumRandom :: forall a g. (Enum a, Bounded a, RandomGen g) => g -> (a, g)
boundedEnumRandom  =  forall a g. (Enum a, RandomGen g) => (a, a) -> g -> (a, g)
enumRandomR (forall a. Bounded a => a
minBound, forall a. Bounded a => a
maxBound)

chooseEnum :: (Enum a, Bounded a, Random a) => QC.Gen a
chooseEnum :: forall a. (Enum a, Bounded a, Random a) => Gen a
chooseEnum = forall a. Random a => (a, a) -> Gen a
QC.choose (forall a. Bounded a => a
minBound, forall a. Bounded a => a
maxBound)


quantityRandomR :: (Random b, RandomGen g) =>
   (a -> b) -> (b -> a) -> (a,a) -> g -> (a,g)
quantityRandomR :: forall b g a.
(Random b, RandomGen g) =>
(a -> b) -> (b -> a) -> (a, a) -> g -> (a, g)
quantityRandomR a -> b
fromQuantity b -> a
toQuantity (a
l,a
r) =
   forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst b -> a
toQuantity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a g. (Random a, RandomGen g) => (a, a) -> g -> (a, g)
randomR (a -> b
fromQuantity a
l, a -> b
fromQuantity a
r)

boundedQuantityRandom :: (Bounded a, Random b, RandomGen g) =>
   (a -> b) -> (b -> a) -> g -> (a,g)
boundedQuantityRandom :: forall a b g.
(Bounded a, Random b, RandomGen g) =>
(a -> b) -> (b -> a) -> g -> (a, g)
boundedQuantityRandom a -> b
fromQuantity b -> a
toQuantity =
   forall b g a.
(Random b, RandomGen g) =>
(a -> b) -> (b -> a) -> (a, a) -> g -> (a, g)
quantityRandomR a -> b
fromQuantity b -> a
toQuantity (forall a. Bounded a => a
minBound, forall a. Bounded a => a
maxBound)

chooseQuantity :: (Bounded a, Random b) =>
   (a -> b) -> (b -> a) -> QC.Gen a
chooseQuantity :: forall a b. (Bounded a, Random b) => (a -> b) -> (b -> a) -> Gen a
chooseQuantity a -> b
fromQuantity b -> a
toQuantity =
   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> a
toQuantity forall a b. (a -> b) -> a -> b
$ forall a. Random a => (a, a) -> Gen a
QC.choose (a -> b
fromQuantity forall a. Bounded a => a
minBound, a -> b
fromQuantity forall a. Bounded a => a
maxBound)


newtype ArbChar = ArbChar {ArbChar -> Char
deconsArbChar :: Char}

instance QC.Arbitrary ArbChar where
   arbitrary :: Gen ArbChar
arbitrary =
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> ArbChar
ArbChar forall a b. (a -> b) -> a -> b
$
      forall a. [(Int, Gen a)] -> Gen a
QC.frequency
         [(Int
26, forall a. Random a => (a, a) -> Gen a
QC.choose (Char
'a',Char
'z')),
          (Int
26, forall a. Random a => (a, a) -> Gen a
QC.choose (Char
'A',Char
'Z')),
          (Int
10, forall a. Random a => (a, a) -> Gen a
QC.choose (Char
'0',Char
'9'))]

arbitraryString :: QC.Gen String
arbitraryString :: Gen String
arbitraryString =
   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map ArbChar -> Char
deconsArbChar) forall a. Arbitrary a => Gen a
QC.arbitrary


newtype ArbByte = ArbByte {ArbByte -> Word8
deconsArbByte :: Word8}

instance QC.Arbitrary ArbByte where
   arbitrary :: Gen ArbByte
arbitrary =
      forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Word8 -> ArbByte
ArbByte forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) forall a b. (a -> b) -> a -> b
$ forall a. Random a => (a, a) -> Gen a
QC.choose (Int
0,Int
0xFF::Int)

arbitraryByteList :: QC.Gen [Word8] -- ByteList
arbitraryByteList :: Gen [Word8]
arbitraryByteList =
   forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. (a -> b) -> [a] -> [b]
map ArbByte -> Word8
deconsArbByte) forall a. Arbitrary a => Gen a
QC.arbitrary