mutable-lens-0.4.1.0: Interoperate mutable references with regular lens
Safe HaskellNone
LanguageHaskell2010

Control.Lens.Mutable

Synopsis

Foundations

data PrimOpGroup Source #

GHC implements different primitive operations, some of which cannot be mixed together and some of which can only be run in certain contexts. In particular, STM-related primops cannot be run directly in the IO monad. However, this restriction is not represented at the bottom layer of the IO runtime which we need to wrap around and expose to users.

This data structure is our ad-hoc attempt to group together "compatible" primops so that only lens representing compatible references can be composed together, avoiding deadly segfaults.

See https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/prelude/primops.txt.pp

See also https://github.com/haskell/primitive/issues/43#issuecomment-613771394

Constructors

OpST 
OpMVar 
OpSTM 

Instances

Instances details
Bounded PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Enum PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Eq PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Ord PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Read PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Show PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Generic PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Associated Types

type Rep PrimOpGroup :: Type -> Type #

type Rep PrimOpGroup Source # 
Instance details

Defined in Control.Lens.Mutable.Types

type Rep PrimOpGroup = D1 ('MetaData "PrimOpGroup" "Control.Lens.Mutable.Types" "mutable-lens-0.4.1.0-1wrPeGuyOfjJfm9OxqoIzD" 'False) (C1 ('MetaCons "OpST" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "OpMVar" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "OpSTM" 'PrefixI 'False) (U1 :: Type -> Type)))

data S p s Source #

Lifted State#. This is needed to interoperate lifted ("normal") types and unlifted types (such as primitives), but it also gives us the chance to restrict composition based on PrimOpGroup which sadly isn't done in the unlifted internal representation, though it could be.

Constructors

S !(State# s) 

Instances

Instances details
Allocable (S 'OpST RealWorld) a IORef Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpMVar RealWorld) a MVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpSTM RealWorld) a TMVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpSTM RealWorld) a TVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

AsLens (S 'OpST RealWorld) a IORef Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: IORef a -> Lens' (S 'OpST RealWorld) a Source #

AsLens (S 'OpMVar RealWorld) a MVar Source #

View a MVar a as a SLens 'OpST RealWorld a.

Note: when this is eventually run in IO, the action will block the thread until there is a value present, as per the semantics of takeMVar#. It will then put a value into the MVar, which will block the thread if the value is absent. GHC doesn't give atomicity guarantees for MVar so it's possible this does happen, e.g. if another producer managed to "get in there" during the intervening period between the two operations. Unfortunately GHC does not provide an atomic modifyMVar function or primop.

If you don't want to deal with this, don't use an MVar, use a TMVar.

Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: MVar a -> Lens' (S 'OpMVar RealWorld) a Source #

AsLens (S 'OpSTM RealWorld) a TMVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: TMVar a -> Lens' (S 'OpSTM RealWorld) a Source #

AsLens (S 'OpSTM RealWorld) a TVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: TVar a -> Lens' (S 'OpSTM RealWorld) a Source #

Allocable (S 'OpST s) a (STRef s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

alloc :: a -> S 'OpST s -> (STRef s a, S 'OpST s) Source #

free :: STRef s a -> S 'OpST s -> (a, S 'OpST s) Source #

isValid :: STRef s a -> S 'OpST s -> (Bool, S 'OpST s) Source #

Allocable (S 'OpST s) a (MutVar s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

alloc :: a -> S 'OpST s -> (MutVar s a, S 'OpST s) Source #

free :: MutVar s a -> S 'OpST s -> (a, S 'OpST s) Source #

isValid :: MutVar s a -> S 'OpST s -> (Bool, S 'OpST s) Source #

AsLens (S 'OpST s) a (STRef s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: STRef s a -> Lens' (S 'OpST s) a Source #

AsLens (S 'OpST s) a (MutVar s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: MutVar s a -> Lens' (S 'OpST s) a Source #

type LST p s r = S p s -> (r, S p s) Source #

A lifted primitive state-transformer that interoperates with lens.

Specifically, this is a bare (unwrapped in StateT) state transition on a lifted ("normal") state type.

To obtain one of these, you may apply a SLens p s a to a bare state transition, i.e. a function of type (a -> (r, a)).

class FromLST p s m where Source #

Convert an LST p to some context m.

This is similar to PrimMonad from the primitives package except our extra p type-param helps us avoid accidentally mixing incompatible primops.

Methods

stToM :: LST p s r -> m r Source #

Instances

Instances details
(PrimMonad m, s ~ PrimState m) => FromLST 'OpST s m Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

stToM :: LST 'OpST s r -> m r Source #

FromLST 'OpMVar RealWorld IO Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

stToM :: LST 'OpMVar RealWorld r -> IO r Source #

FromLST 'OpSTM RealWorld STM Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

stToM :: LST 'OpSTM RealWorld r -> STM r Source #

class FromLST p s m => IsoLST p s m where Source #

Convert an LST p to and from some context m.

This is similar to PrimBase from the primitives package except our extra p type-param helps us avoid accidentally mixing incompatible primops.

Methods

mToST :: m r -> LST p s r Source #

Instances

Instances details
(PrimBase m, s ~ PrimState m) => IsoLST 'OpST s m Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

mToST :: m r -> LST 'OpST s r Source #

IsoLST 'OpMVar RealWorld IO Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

mToST :: IO r -> LST 'OpMVar RealWorld r Source #

IsoLST 'OpSTM RealWorld STM Source # 
Instance details

Defined in Control.Lens.Mutable.Types

Methods

mToST :: STM r -> LST 'OpSTM RealWorld r Source #

type MonadLST p s m = (FromLST p s m, Monad m) Source #

Convert an 'LST p from some monadic action m.

type SLens p s a = Lens' (S p s) a Source #

Representation of a mutable reference as a Lens'.

When the lens functor type-param is (,) r, then the output transition function is of type LST s r. To use it as a monadic action e.g. to run it, you'll need to first convert it using stToM.

Again, in principle this ought not to be necessary, but the Haskell runtime forces us to do this due to historical design decisions to hide necessary details that seemed appropriate to hide at the time.

type ASLens p s a = ALens' (S p s) a Source #

Representation of a mutable reference as a ALens'.

This type is useful if you need to store a lens in a container. To recover the original type, pass it through cloneLens.

Convenience utilities

runSLens :: FromLST p s m => LensLike' ((,) r) (S p s) a -> (a -> (r, a)) -> m r Source #

Run a bare state transition on a lens in the monad for p.

The lens may be an SLens p or any compositions of it with other optics, including prisms and so forth.

runASLens :: FromLST p s m => ALens' (S p s) a -> (a -> (r, a)) -> m r Source #

Run a bare state transition on an ALens' in the monad for p.

stateRead :: a -> (a, a) Source #

A bare state transition representing a read operation.

stateWrite :: b -> a -> ((), b) Source #

A bare state transition representing a write operation.

stateWrite b can be passed to runSLens to write b to the reference.

stateModify :: (a -> b) -> a -> ((), b) Source #

A bare state transition representing a modify/map operation.

stateModify f can be passed to runSLens to apply f to the reference.

Typeclasses and instances

class AsLens s a ref where Source #

Convert a reference type to a Lens'.

Methods

asLens :: ref a -> Lens' s a Source #

Instances

Instances details
AsLens (S 'OpST RealWorld) a IORef Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: IORef a -> Lens' (S 'OpST RealWorld) a Source #

AsLens (S 'OpMVar RealWorld) a MVar Source #

View a MVar a as a SLens 'OpST RealWorld a.

Note: when this is eventually run in IO, the action will block the thread until there is a value present, as per the semantics of takeMVar#. It will then put a value into the MVar, which will block the thread if the value is absent. GHC doesn't give atomicity guarantees for MVar so it's possible this does happen, e.g. if another producer managed to "get in there" during the intervening period between the two operations. Unfortunately GHC does not provide an atomic modifyMVar function or primop.

If you don't want to deal with this, don't use an MVar, use a TMVar.

Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: MVar a -> Lens' (S 'OpMVar RealWorld) a Source #

AsLens (S 'OpSTM RealWorld) a TMVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: TMVar a -> Lens' (S 'OpSTM RealWorld) a Source #

AsLens (S 'OpSTM RealWorld) a TVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: TVar a -> Lens' (S 'OpSTM RealWorld) a Source #

AsLens (S 'OpST s) a (STRef s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: STRef s a -> Lens' (S 'OpST s) a Source #

AsLens (S 'OpST s) a (MutVar s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

asLens :: MutVar s a -> Lens' (S 'OpST s) a Source #

class AsLens s a ref => Allocable s a ref where Source #

A state in which you can allocate new references.

This can be defined on either pure or impure references. For pure references one could e.g. define an instance of this on Map k v with Const k as the reference type - see unit tests for an example.

Minimal complete definition

alloc

Methods

alloc :: a -> s -> (ref a, s) Source #

Allocate a new reference with the given value.

free :: HasCallStack => ref a -> s -> (a, s) Source #

Deallocate an existing reference, and return its value.

The default implementation simply writes error into the reference and returns the old value. The caller is responsible for actually throwing away the reference and never using it again, as per Haskell's GC semantics.

isValid :: ref a -> s -> (Bool, s) Source #

Check if a reference is valid.

The default implementation simply forces the reference and returns True. If the reference has already been freed (via free) then an error will be raised, which you can catch in the IO monad as per usual. In other words, the default implementation will never return False.

Instances

Instances details
Allocable (S 'OpST RealWorld) a IORef Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpMVar RealWorld) a MVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpSTM RealWorld) a TMVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpSTM RealWorld) a TVar Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Allocable (S 'OpST s) a (STRef s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

alloc :: a -> S 'OpST s -> (STRef s a, S 'OpST s) Source #

free :: STRef s a -> S 'OpST s -> (a, S 'OpST s) Source #

isValid :: STRef s a -> S 'OpST s -> (Bool, S 'OpST s) Source #

Allocable (S 'OpST s) a (MutVar s) Source # 
Instance details

Defined in Control.Lens.Mutable.Internal

Methods

alloc :: a -> S 'OpST s -> (MutVar s a, S 'OpST s) Source #

free :: MutVar s a -> S 'OpST s -> (a, S 'OpST s) Source #

isValid :: MutVar s a -> S 'OpST s -> (Bool, S 'OpST s) Source #