{-# LANGUAGE ScopedTypeVariables #-}

module ROC.ID.Utilities where

import Control.Monad.Random.Class
    ( MonadRandom (..) )
import Data.Maybe
    ( listToMaybe )

guard :: x -> Maybe y -> Either x y
guard :: forall x y. x -> Maybe y -> Either x y
guard x
x = Either x y -> (y -> Either x y) -> Maybe y -> Either x y
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (x -> Either x y
forall a b. a -> Either a b
Left x
x) y -> Either x y
forall a b. b -> Either a b
Right

maybeRead :: Read a => String -> Maybe a
maybeRead :: forall a. Read a => String -> Maybe a
maybeRead = ((a, String) -> a) -> Maybe (a, String) -> Maybe a
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, String) -> a
forall a b. (a, b) -> a
fst (Maybe (a, String) -> Maybe a)
-> (String -> Maybe (a, String)) -> String -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(a, String)] -> Maybe (a, String)
forall a. [a] -> Maybe a
listToMaybe ([(a, String)] -> Maybe (a, String))
-> (String -> [(a, String)]) -> String -> Maybe (a, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [(a, String)]
forall a. Read a => ReadS a
reads

maybeToEnum :: forall a . Bounded a => Enum a => Int -> Maybe a
maybeToEnum :: forall a. (Bounded a, Enum a) => Int -> Maybe a
maybeToEnum Int
i
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< a -> Int
forall a. Enum a => a -> Int
fromEnum (a
forall a. Bounded a => a
minBound :: a) = Maybe a
forall a. Maybe a
Nothing
  | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> a -> Int
forall a. Enum a => a -> Int
fromEnum (a
forall a. Bounded a => a
maxBound :: a) = Maybe a
forall a. Maybe a
Nothing
  | Bool
otherwise                    = a -> Maybe a
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ Int -> a
forall a. Enum a => Int -> a
toEnum Int
i

randomBoundedEnum :: forall a m . MonadRandom m => Bounded a => Enum a => m a
randomBoundedEnum :: forall a (m :: * -> *). (MonadRandom m, Bounded a, Enum a) => m a
randomBoundedEnum =
  Int -> a
forall a. Enum a => Int -> a
toEnum (Int -> a) -> m Int -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int, Int) -> m Int
forall a. Random a => (a, a) -> m a
forall (m :: * -> *) a. (MonadRandom m, Random a) => (a, a) -> m a
getRandomR (a -> Int
forall a. Enum a => a -> Int
fromEnum (a
forall a. Bounded a => a
minBound :: a), a -> Int
forall a. Enum a => a -> Int
fromEnum (a
forall a. Bounded a => a
maxBound :: a))