{-# LANGUAGE NoIncoherentInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}

module Vivid.Randomness (
     pick
   , picks
   , exprand
   , module System.Random.Shuffle
   ) where

import Control.Monad.Random (getRandomR, getRandomRs, MonadRandom)
import System.Random (Random)
import System.Random.Shuffle

-- | Picks a random element from the provided list
pick :: MonadRandom m => [a] -> m a
pick :: [a] -> m a
pick [a]
l = ([a]
l [a] -> Int -> a
forall a. [a] -> Int -> a
!!) (Int -> a) -> m Int -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int) -> m Int
forall (m :: * -> *) a. (MonadRandom m, Random a) => (a, a) -> m a
getRandomR (Int
0, (forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length::[a]->Int) [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

-- | Returns an infinite list of randomly-chosen elements from the provided list
-- 
--   e.g.
-- 
--   >> > take 5 <$> picks [1,2,3,4]
--   >> [2,3,1,1,3]
picks :: (MonadRandom m) => [a] -> m [a]
picks :: [a] -> m [a]
picks [a]
l =
   ((Int -> a) -> [Int] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map ([a]
l [a] -> Int -> a
forall a. [a] -> Int -> a
!!)) ([Int] -> [a]) -> m [Int] -> m [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int) -> m [Int]
forall (m :: * -> *) a.
(MonadRandom m, Random a) =>
(a, a) -> m [a]
getRandomRs (Int
0, (forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length::[a]->Int) [a]
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)

exprand :: (Fractional n, Floating n, MonadRandom m, Random n) => n -> n -> m n
exprand :: n -> n -> m n
exprand n
lo n
hi = do
   n
r <- (n, n) -> m n
forall (m :: * -> *) a. (MonadRandom m, Random a) => (a, a) -> m a
getRandomR (n
0, n
1)
   n -> m n
forall (f :: * -> *) a. Applicative f => a -> f a
pure (n -> m n) -> n -> m n
forall a b. (a -> b) -> a -> b
$ n
lo n -> n -> n
forall a. Num a => a -> a -> a
* n -> n
forall a. Floating a => a -> a
exp (n -> n
forall a. Floating a => a -> a
log (n
hi n -> n -> n
forall a. Fractional a => a -> a -> a
/ n
lo) n -> n -> n
forall a. Num a => a -> a -> a
* n
r)