-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Fields for Monadic Records library -- -- The generalized, extensible syntax of abstract monadic records. @package fmr @version 0.2 -- | Data.Property new-style properties. module Data.Property -- | IsProp is a property class that allows you to extend -- fmr syntax. Now you can create new property types and use it -- with existing in set list of actions. class IsProp (prop :: PropertyKind) -- | performProp record prop performs an action on -- record using prop. performProp :: (IsProp prop, Monad m) => record -> prop m field record -> m () -- | @since 0.2 Service kind synonym. type PropertyKind = (Type -> Type) -> FieldKind -> Type -> Type -- | @since 0.2 Service kind synonym. type FieldKind = (Type -> Type) -> Type -> Type -> Type -- | Prop is new, generalized and extensible property type -- (existential), which may contain any IsProp value. data Prop m field record [Prop] :: (Monad m, IsProp prop) => prop m field record -> Prop m field record -- | @since 0.2 Property getter class. class FieldGet field -- | getRecord field record return record's value -- using field. getRecord :: (FieldGet field, Monad m) => field m record a -> record -> m a -- | The get function reads current value of a field. get :: (Monad m, FieldGet field) => field m record a -> record -> m a -- | gets' fields record returns list of record -- fields values. gets' :: (Monad m, FieldGet field) => record -> [field m record a] -> m [a] -- | @since 0.2 Property setter class. class FieldSet field -- | setRecord field record value sets new record -- value. setRecord :: (FieldSet field, Monad m) => field m record a -> record -> a -> m () -- | set is the main function in fmr, which allows you to -- describe changing the value of a record as a sequence of operations on -- its fields, e.g. set :: Monad m => record -> [Prop m field record] -> m () -- | Just synonym for set. sets' :: Monad m => record -> [Prop m field record] -> m () -- | Pure value setter. set record [field := value] set -- value to record's field. pattern (:=) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => field m record a -> a -> Prop m field record -- | Pure value setter with record. set record [field ::= -- f] set f record to record's field. -- --
-- set record [field ::= const val] === set record [field := val] -- --pattern (::=) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => field m record a -> (record -> a) -> Prop m field record -- | Pure group setter. set record [fields :=$ value] set -- value to record's some fields. -- --
-- set record [[field] :=$ value] === set record [field := value] -- --pattern (:=$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => [field m record a] -> a -> Prop m field record -- | Pure group setter with record. set record [fields ::=$ -- f] set f record to record's some -- fields. -- --
-- set record [[field] ::=$ f] === set record [field ::= f] -- set record [fields ::=$ const val] === set record [fields :=$ val] -- --pattern (::=$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => [field m record a] -> (record -> a) -> Prop m field record -- | Monadic value setter. set record [field :<= mvalue] set -- result of mvalue to record's field. Note -- that the mvalue is evaluated every time a field -- value is assigned. -- --
-- set record [field :<= return val] === set record [field := val] -- set record [field :<= mval] === do val <- mval; set record [field :<= val] -- --pattern (:<=) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => field m record a -> m a -> Prop m field record -- | Monadic group setter. set record [fields :<=$ mvalue] set -- result of mvalue to record's fields. Note -- that mvalue is evaluated only once, on the first assignment. -- Thus, the values of all the listed fields will be identical. -- --
-- set record [[field] :<=$ const f] === set record [field :<= val] -- set record [fields :<=$ mval] === do val <- mval; set record [fields :<=$ val] -- --pattern (:<=$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => [field m record a] -> m a -> Prop m field record -- | Monadic value setter with record. set record [field -- :=< mvalue] set result of mvalue record to -- record's field. Note that the mvalue is -- evaluated every time a field value is assigned. -- --
-- set record [field :=< const val] === set record [field :<= val] -- set record [field :=< f] === do val <- f record; set record [field := val] -- --pattern (:=<) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => field m record a -> (record -> m a) -> Prop m field record -- | Monadic group setter with record. set record [fields -- :=<$ f] set result of f record to record's -- fields. Note that f record is evaluated only once, -- on the first assignment. Thus, the values of all the listed fields -- will be identical. -- --
-- set record [[field] :=<$ f] === set record [field :=< val] -- set record [fields :=<$ const val] = set record [fields :=$ val] -- set record [fields :=<$ f] === do val <- f record; set record [fields :=$ val] -- --pattern (:=<$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldSet field) => [field m record a] -> (record -> m a) -> Prop m field record -- | Property modifier class. -- -- Note that FieldModifier doesn't go well with write-only -- fields, because modifyRecord returns new value, and -- modifyRecordM also assumes the possibility of old value -- "leaking" (hence the FieldGet constraint is imposed on it). class (FieldSet field) => FieldModify field -- | modifyRecord field record upd modifies record -- field using upd. Returns new value. modifyRecord :: (FieldModify field, Monad m, FieldGet field) => field m record a -> record -> (a -> a) -> m a -- | modifyRecord field record upd modifies record -- field using upd. Returns new value. modifyRecord :: (FieldModify field, Monad m) => field m record a -> record -> (a -> a) -> m a -- | modifyRecordM field record upd modifies -- record field using upd. Note that assumes -- the possibility of old value "leaking", e.g.: -- --
-- -- get value using modifyRecordM -- getLeak = do -- -- Some read-only fields -- x <- newWriteOnly -- y <- var Nothing -- -- write current value to y and do not modify. -- modifyRecordM this x ( val -> do set [this := Just val]; return val) -- -- leaking: return current value of "write-only" record -- get this y -- ---- -- So you cannot use it for write-only fields. modifyRecordM :: (FieldModify field, Monad m, FieldGet field) => field m record a -> record -> (a -> m a) -> m a -- | Pure value modifier. set record [field :~ f] modify value of -- record's field using f function. -- --
-- set record [field :~ const val] === set record [field := val] -- --pattern (:~) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field) => field m record a -> (a -> a) -> Prop m field record -- | Pure group modifier. set record [fields :~$ f] modify values -- of record's fields using f function. -- --
-- set record [[field] :~$ val] === set record [field :~ val] -- set record [fields :~$ const val] === set record [field :=$ val] -- --pattern (:~$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field) => [field m record a] -> (a -> a) -> Prop m field record -- | Pure value modifier with record. set record [field ::~ -- f] modify value of record's field using f -- record function. -- --
-- set record [field ::~ const f] === set record [field :~ f] -- --pattern (::~) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field) => field m record a -> (record -> a -> a) -> Prop m field record -- | Pure group modifier with record. set record [fields ::~$ -- f] modify values of record's fields using f -- record function. -- --
-- set record [[field] ::~$ f] === set record [field ::~ f] -- set record [fields ::~$ const f] === set record [field :~$ f] -- --pattern (::~$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field) => [field m record a] -> (record -> a -> a) -> Prop m field record -- | Monadic value modifier. set record [field :<~ f] modifies -- value of record's field using f procedure. -- Note that the mvalue is called every time a field -- value is assigned. -- --
-- set record [field :<~ return val] === set record [fields := val] -- --pattern (:<~) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field, FieldGet field) => field m record a -> (a -> m a) -> Prop m field record -- | Monadic group modifier. set record [fields :<~$ f] -- modifies values of record's fields using f -- procedure. -- --
-- set record [[field] :<~$ f] === set record [field :<~ f] -- set record [fields :<~$ const mval] === set record [field :<=$ mval] -- --pattern (:<~$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field, FieldGet field) => [field m record a] -> (a -> m a) -> Prop m field record -- | Monadic value modifier with record. set record [field -- :<~ f] modifies value of record's field -- using f record procedure. Note that the f record is -- called every time a field value is assigned. -- --
-- set record [field :~< const f] === set record [fields :<~ f] -- --pattern (:~<) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field, FieldGet field) => field m record a -> (record -> a -> m a) -> Prop m field record -- | Monadic group modifier with record. set record [fields -- :~<$ f] modifies values of record's fields -- using f record procedure. Note that the f record is -- called every time a field value is assigned. -- --
-- set record [field :~<$ const f] === set record [fields :<~$ f] -- --pattern (:~<$) :: (Typeable m, Typeable field, Typeable record, Monad m, FieldModify field, FieldGet field) => [field m record a] -> (record -> a -> m a) -> Prop m field record -- | Service class for switchable types. class IsSwitch switch -- | toggle s n "toggles" the state represented by the -- value s by n positions, for example: -- --
-- toggle n False = even n -- toggle n True = odd n -- toggle n 1234 = 1239 + n -- --toggle :: IsSwitch switch => Int -> switch -> switch -- | Switch property modifier. -- -- Note that FieldSwitch is designed for deterministic switches -- with a pre-known set of states and order of transitions between them, -- without branches. If you need more complex behavior, use -- FieldModify. class FieldSwitch field -- | Repeated increment or decrement. switchRecord :: (FieldSwitch field, Monad m, IsSwitch a) => field m record a -> record -> Int -> m () -- | switch changes the value by n steps. switch :: (Monad m, FieldSwitch field, IsSwitch a) => field m record a -> Int -> Prop m field record -- | incr field is same as switch field 1. incr :: (Monad m, FieldSwitch field, IsSwitch a) => field m record a -> Prop m field record -- | decr field is same as switch field (-1). decr :: (Monad m, FieldSwitch field, IsSwitch a) => field m record a -> Prop m field record instance Data.Property.IsProp Data.Property.SwitchProp instance Data.Property.IsSwitch GHC.Types.Bool instance GHC.Real.Integral i => Data.Property.IsSwitch i instance Data.Property.IsProp Data.Property.ModifyProp instance Data.Property.IsProp Data.Property.SetProp -- | Data.Field.Observe simple field observer. module Data.Field.Observe -- | Simple field observer, which can run some handlers after each action. data Observe field m record a Observe :: field m record a -> (record -> a -> m ()) -> (record -> a -> m ()) -> (record -> m ()) -> Observe field m record a -- | Field to observe. [observed] :: Observe field m record a -> field m record a -- | getRecord observer [onGet] :: Observe field m record a -> record -> a -> m () -- | setRecord observer [onSet] :: Observe field m record a -> record -> a -> m () -- | modifyRecord observer [onModify] :: Observe field m record a -> record -> m () -- | Create field with default observers. observe :: Monad m => field m record a -> Observe field m record a instance Data.Property.FieldSwitch field => Data.Property.FieldSwitch (Data.Field.Observe.Observe field) instance Data.Property.FieldGet field => Data.Property.FieldGet (Data.Field.Observe.Observe field) instance Data.Property.FieldSet field => Data.Property.FieldSet (Data.Field.Observe.Observe field) instance (Data.Property.FieldModify field, Data.Property.FieldGet field) => Data.Property.FieldModify (Data.Field.Observe.Observe field) -- | Data.Field provides immutable field type for record-style -- operations. module Data.Field -- | Normal field, which contain getter, setter and modifier. -- -- Since fmr-0.2, you can also combine fmr fields using -- (.) and id from the Category -- class: -- --
-- outer :: (Monad m) => Field m outer inner -- inner :: (Monad m) => Field m inner value -- -- field :: (Monad m) => Field m outer value -- field = outer.inner -- --data Field m record a Field :: !GetterFor m record a -> !SetterFor m record a -> !ModifierFor m record a -> !ModifierMFor m record a -> Field m record a -- | Field getter [getField] :: Field m record a -> !GetterFor m record a -- | Field setter [setField] :: Field m record a -> !SetterFor m record a -- | Field modifier [modifyField] :: Field m record a -> !ModifierFor m record a -- | Monadic field modifier [modifyFieldM] :: Field m record a -> !ModifierMFor m record a -- | sfield creates new field from given getter and setter. sfield :: Monad m => GetterFor m record a -> SetterFor m record a -> Field m record a -- | Getter type. type GetterFor m record a = record -> m a -- | Setter type. type SetterFor m record a = record -> a -> m () -- | Modifier type. type ModifierFor m record a = record -> (a -> a) -> m a -- | Monadic modifier type. type ModifierMFor m record a = record -> (a -> m a) -> m a -- | The IsMVar class provides this field for entire record -- access. -- -- Please note that you cannot create IsMVar and MonadVar -- instances for some monad separately. class (Monad m, MonadVar m) => IsMVar m var -- | this is common variable access field. this :: IsMVar m var => Field m (var a) a -- | Create and initialize new mutable variable. var :: IsMVar m var => a -> m (var a) -- | MonadVar is a class of monads for which defined at least one -- type of mutable variable. -- -- Note that a variable of type (Var m) should be as simple -- possible for a given monad. I only has to implement the basic -- operations triad: read, write and update (which don't have to be -- atomic). class (Monad m, IsMVar m (Var m)) => MonadVar m where { -- | (Var m) is type of mutable variable in monad -- m. type family Var m :: Type -> Type; } instance Data.Field.IsMVar (GHC.ST.ST s) (GHC.STRef.STRef s) instance Data.Field.IsMVar GHC.Types.IO GHC.IORef.IORef instance Data.Field.IsMVar GHC.Types.IO GHC.MVar.MVar instance Data.Field.IsMVar GHC.Conc.Sync.STM GHC.Conc.Sync.TVar instance Data.Field.MonadVar (GHC.ST.ST s) instance Data.Field.MonadVar GHC.Types.IO instance Data.Field.MonadVar GHC.Conc.Sync.STM instance GHC.Base.Monad m => Control.Category.Category (Data.Field.Field m) instance Data.Property.FieldGet Data.Field.Field instance Data.Property.FieldSet Data.Field.Field instance Data.Property.FieldModify Data.Field.Field instance Data.Property.FieldSwitch Data.Field.Field -- | Data.MField provides mutable field type for record-style -- operations. module Data.MField -- | MField represents field with mutable value and accessors. -- Unlike fields of type Field, MField fields are -- undesirable (and sometimes impossible) to be stored in the global -- environment. The dynamic nature of MField means changing -- accessors for specific records, so accessors do not contain a record -- argument. -- -- MField isn't designed for accessing external abstract objects -- and interfaces, it doesn't give the same freedom as Field, but -- at the same time it allows you to create flexible connections between -- fields and values without having to reconcile them. -- -- MField contains a function that takes a record and returns an -- MFieldRef. -- -- Example: -- --
-- newtype HasField a = HasField {someField :: MFieldRep IO a}
--
-- field :: MField IO (HasField a) a
-- field = MField (ref.someField)
--
-- main :: IO ()
-- main = do
-- putStrLn "Put some number"
-- record <- fmap HasField $ link =<< var =<< readLn :: IO (HasField Integer)
-- print =<< get field record
--
-- set record [getter field :~ fmap (* 2)]
-- print =<< get field record
--
--
data MField m record a
[MField] :: MonadVar m => (record -> MFieldRef m a) -> MField m record a
class IsRef ref
-- | Create new reference to the given variable.
link :: (IsRef ref, MonadVar m) => Var m a -> m (ref m a)
-- | Get an associated MFieldRef reference to the given reference.
ref :: (IsRef ref, MonadVar m) => ref m a -> MFieldRef m a
-- | MFieldRef is a structure containing accessors for a specific
-- field of a specific record. As a rule, it makes sense to store
-- MFieldRef in the record to which it refers.
data MFieldRef m a
-- | MFieldRep is a helper type that stores a variable and its
-- accessors.
data MFieldRep m a
getter :: MField m record a -> Field m record (m a)
setter :: MField m record a -> Field m record (a -> m ())
modifier :: MField m record a -> Field m record ((a -> a) -> m a)
modifierM :: MField m record a -> Field m record ((a -> m a) -> m a)
instance Data.MField.IsRef Data.MField.MFieldRep
instance Data.Property.FieldGet Data.MField.MField
instance Data.Property.FieldSet Data.MField.MField
instance Data.Property.FieldModify Data.MField.MField
instance Data.Property.FieldSwitch Data.MField.MField
instance Data.MField.IsRef Data.MField.MFieldRef