{-# LANGUAGE ScopedTypeVariables #-}

module Control.Monad.TransLogicState.Class
  ( TransLogicState(..)
  
  , observe
  , observeAll
  , observeMany
  )
  where

-- import Data.Typeable

import Control.Arrow
import Control.Monad.Identity
import Control.Monad.Trans

-- | Additions to MonadTrans specifically useful for LogicState
class MonadTrans t => TransLogicState s t where
  -------------------------------------------------------------------------
  -- | Extracts the first result from a 't m' computation,
  -- failing otherwise.
  observeT :: (MonadFail m) => s -> t m a -> m a
  observeT s
e t m a
m = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [a] -> a
head forall a b. (a -> b) -> a -> b
$ forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> Int -> t m a -> m [a]
observeManyT s
e Int
1 t m a
m
  
  -------------------------------------------------------------------------
  -- | Extracts all results from a 't m' computation.
  observeAllT :: (Monad m) => s -> t m a -> m [a]
  observeAllT s
e = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> t m a -> m ([a], s)
observeStateAllT s
e
  
  -------------------------------------------------------------------------
  -- | Extracts all results from a 't m' computation.
  observeStateAllT :: (Monad m) => s -> t m a -> m ([a],s)
  observeStateAllT s
e = forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> Int -> t m a -> m ([a], s)
observeStateManyT s
e forall a. Bounded a => a
maxBound
  
  -------------------------------------------------------------------------
  -- | Extracts up to a given number of results from a 't m' computation.
  observeManyT :: forall m a . (Monad m) => s -> Int -> t m a -> m [a]
  observeManyT s
e Int
n t m a
m = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> Int -> t m a -> m ([a], s)
observeStateManyT s
e Int
n t m a
m

  -------------------------------------------------------------------------
  -- | Extracts up to a given number of results from a 't m' computation.
  observeStateManyT :: forall m a . (Monad m) => s -> Int -> t m a -> m ([a],s)
  observeStateManyT s
e Int
n t m a
m = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first forall a b. (a -> b) -> a -> b
$ forall a. Int -> [a] -> [a]
take Int
n) forall a b. (a -> b) -> a -> b
$ forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> t m a -> m ([a], s)
observeStateAllT s
e t m a
m

  -- | Lift a monad by threading the state available in the transformed monad through it
  liftWithState :: Monad m => (s -> m (a,s)) -> t m a

-------------------------------------------------------------------------
-- | Extracts the first result from a LogicVar computation.
observe :: (TransLogicState s t) => s -> t Maybe a -> Maybe a
observe :: forall s (t :: (* -> *) -> * -> *) a.
TransLogicState s t =>
s -> t Maybe a -> Maybe a
observe s
e = forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, MonadFail m) =>
s -> t m a -> m a
observeT s
e

-------------------------------------------------------------------------
-- | Extracts all results from a LogicVar computation.
observeAll :: (TransLogicState s t) => s -> t Identity a -> [a]
observeAll :: forall s (t :: (* -> *) -> * -> *) a.
TransLogicState s t =>
s -> t Identity a -> [a]
observeAll s
e = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> t m a -> m [a]
observeAllT s
e

-------------------------------------------------------------------------
-- | Extracts up to a given number of results from a LogicVar computation.
observeMany :: (TransLogicState s t) => s -> Int -> t Identity a -> [a]
observeMany :: forall s (t :: (* -> *) -> * -> *) a.
TransLogicState s t =>
s -> Int -> t Identity a -> [a]
observeMany s
e Int
i = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(TransLogicState s t, Monad m) =>
s -> Int -> t m a -> m [a]
observeManyT s
e Int
i