packages feed

imprevu-0.1.0: src/Imprevu/Variables.hs

{-# 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