content: {-# LANGUAGE RankNTypes #-}
  {-# LANGUAGE LambdaCase #-}
  module PreludeExtra
      ( module Exports
      , module PreludeExtra
      ) where
  
  import Control.Monad.State as Exports hiding (withState, withStateT)
  import Control.Monad.Reader as Exports hiding (local)
  import Control.Monad.Trans.Control as Exports hiding (control)
  import Data.Maybe as Exports
  import Data.Monoid as Exports
  import Data.Foldable as Exports
  import Control.Arrow as Exports
  import Control.Concurrent as Exports
  import Control.Concurrent.STM as Exports hiding (atomically)
  
  import Data.Char as Exports
  import Text.Read as Exports (readMaybe)
  import Text.Printf as Exports
  import Data.List as Exports (sort)
  
  import System.Random as Exports
  import System.Directory as Exports
  import System.FilePath as Exports
  import System.Environment as Exports
  
  import Data.Dynamic as Exports
  import Debug.Trace as Exports
  import Data.Fixed as Exports
  import Data.Time as Exports
  import Data.IORef as Exports
  import System.Mem as Exports
  
  import Control.Monad.Catch as Exports
  import Control.DeepSeq as Exports
  
  import Data.Yaml as Exports (FromJSON, ToJSON)
  import GHC.Generics as Exports (Generic)
  
  import Control.Lens.Extra as Exports hiding (List, (<.>), children)
  import Linear.Extra as Exports hiding (trace)
  
  import Graphics.GL.Pal as Exports hiding (trace, getNow, ColorSpace(..)) -- using a faster getNow in Types
  import Graphics.VR.Pal as Exports hiding (getNow, getDeltaTime)
  import Animation.Pal   as Exports hiding (getNow, exhaustTChan)
  
  import Data.ECS as Exports
  
  import Data.Sequence as Exports (Seq)
  
  -- import qualified Data.Map as Map
  import qualified Control.Concurrent.STM as STM
  
  -- useMapM_ :: (MonadState s m) => Lens' s (Map k v) -> ((k,v) -> m b) -> m ()
  -- useMapM_ aLens f = traverseM_ (Map.toList <$> use aLens) f
  
  
  traverseM :: (Monad m, Traversable t) => m (t a) -> (a -> m b) -> m (t b)
  traverseM f x = f >>= traverse x
  
  traverseM_ :: (Monad m, Foldable t) => m (t a) -> (a -> m b) -> m ()
  traverseM_ f x = f >>= traverse_ x
  
  useTraverseM_ :: (MonadState s m, Foldable t) => Lens' s (t a) -> (a -> m b) -> m ()
  useTraverseM_ aLens f = traverseM_ (use aLens) f
  
  for :: [a] -> (a -> b) -> [b]
  for = flip map
  
  exhaustTChan :: TChan a -> STM [a]
  exhaustTChan chan = tryReadTChan chan >>= \case
      Just a -> (a:) <$> exhaustTChan chan
      Nothing -> return []
  
  atomically :: MonadIO m => STM a -> m a
  atomically = liftIO . STM.atomically
  
  orientToward :: (Floating a, Epsilon a) => V3 a -> V3 a -> V3 a -> M44 a
  orientToward eye target up = inv44 (lookAt eye target up)
  