{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} module Imprevu.Variables -- V(..), -- newVar, newVar_, newVar', -- readVar, readVar_, -- writeVar, -- modifyVar, -- delVar, -- getTempVar where import Imprevu.SysMgt import Imprevu.Events import Data.Typeable import Control.Monad.Loops import Control.Monad.Except type VarName = String -- | a container for a variable name and type data V a = V {varName :: VarName} deriving Typeable class (Monad n) => VarMgt n where newVar :: (Typeable a, Show a) => VarName -> a -> n (Maybe (V a)) readVar :: (Typeable a, Show a) => V a -> n (Maybe a) writeVar :: (Typeable a, Show a) => V a -> a -> n Bool delVar :: (V a) -> n Bool -- * Variables -- | variable creation newVar_ :: (Typeable a, Show a, VarMgt n, MonadError String n) => VarName -> a -> n (V a) newVar_ s a = partial "newVar_: Variable existing" (newVar s a) newVar' :: (Typeable a, Show a, VarMgt n) => V a -> a -> n Bool newVar' v a = maybe False (const True) <$> (newVar (varName v) a) -- | variable reading readVar_ :: (Typeable a, Show a, VarMgt n, MonadError String n) => V a -> n a readVar_ v@(V a) = partial ("readVar_: Variable \"" ++ a ++ "\" with type \"" ++ (show $ typeOf v) ++ "\" not existing") (readVar v) -- | modify a variable using the provided function modifyVar :: (Typeable a, Show a, VarMgt n, MonadError String n) => V a -> (a -> a) -> n Bool modifyVar v f = writeVar v . f =<< readVar_ v -- | get temporary variable with random name getTempVar :: (Typeable a, Show a, VarMgt n, SysMgt n) => a -> n (V a) getTempVar a = untilJust $ do r <- getRandomNumber (0, 1000000 :: Int) newVar ("tempVar" ++ (show r)) a