{-# LANGUAGE Safe, GADTs #-}

{- |
    License     :  BSD-style
    Module      :  Data.MField
    Copyright   :  (c) Andrey Mulik 2020-2021
    Maintainer  :  work.a.mulik@gmail.com
    
    @Data.MField@ provides mutable field type for record-style operations.
-}
module Data.MField
(
  -- * Exports
  module Data.Property,
  module Data.Field,
  
  -- * Mutable field
  MField (..), IsRef (..), MFieldRef, MFieldRep,
  getter, setter, modifier, modifierM
)
where

import Data.Typeable
import Data.Property
import Data.Field

import Control.Monad

default ()

--------------------------------------------------------------------------------

{- |
  @since 0.2
  
  '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
  where
    MField :: (MonadVar m) => (record -> MFieldRef m a) -> MField m record a
  deriving ( Typeable )

instance FieldGet MField
  where
    getRecord :: MField m record a -> record -> m a
getRecord (MField record -> MFieldRef m a
field) = m (m a) -> m a
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join(m (m a) -> m a) -> (record -> m (m a)) -> record -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Field m (Var m (m a)) (m a) -> Var m (m a) -> m (m a)
forall (m :: * -> *) (field :: (* -> *) -> * -> * -> *) record a.
(Monad m, FieldGet field) =>
field m record a -> record -> m a
get Field m (Var m (m a)) (m a)
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this(Var m (m a) -> m (m a))
-> (record -> Var m (m a)) -> record -> m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m (m a)
getRef(MFieldRef m a -> Var m (m a))
-> (record -> MFieldRef m a) -> record -> Var m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
field

instance FieldSet MField
  where
    setRecord :: MField m record a -> record -> a -> m ()
setRecord (MField record -> MFieldRef m a
field) record
record a
value = do
      a -> m ()
g <- Field m (Var m (a -> m ())) (a -> m ())
-> Var m (a -> m ()) -> m (a -> m ())
forall (m :: * -> *) (field :: (* -> *) -> * -> * -> *) record a.
(Monad m, FieldGet field) =>
field m record a -> record -> m a
get Field m (Var m (a -> m ())) (a -> m ())
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this(Var m (a -> m ()) -> m (a -> m ()))
-> (record -> Var m (a -> m ())) -> record -> m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (a -> m ())
forall (m :: * -> *) a. MFieldRef m a -> Var m (a -> m ())
setRef(MFieldRef m a -> Var m (a -> m ()))
-> (record -> MFieldRef m a) -> record -> Var m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
field (record -> m (a -> m ())) -> record -> m (a -> m ())
forall a b. (a -> b) -> a -> b
$ record
record; a -> m ()
g a
value

instance FieldModify MField
  where
    modifyRecord :: MField m record a -> record -> (a -> a) -> m a
modifyRecord (MField record -> MFieldRef m a
field) record
record a -> a
upd = do
      (a -> a) -> m a
m <- Field m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
-> Var m ((a -> a) -> m a) -> m ((a -> a) -> m a)
forall (m :: * -> *) (field :: (* -> *) -> * -> * -> *) record a.
(Monad m, FieldGet field) =>
field m record a -> record -> m a
get Field m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this(Var m ((a -> a) -> m a) -> m ((a -> a) -> m a))
-> (record -> Var m ((a -> a) -> m a))
-> record
-> m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef(MFieldRef m a -> Var m ((a -> a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
field (record -> m ((a -> a) -> m a)) -> record -> m ((a -> a) -> m a)
forall a b. (a -> b) -> a -> b
$ record
record; (a -> a) -> m a
m a -> a
upd
    
    modifyRecordM :: MField m record a -> record -> (a -> m a) -> m a
modifyRecordM (MField record -> MFieldRef m a
field) record
record a -> m a
go = do
      (a -> m a) -> m a
mm <- Field m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
-> Var m ((a -> m a) -> m a) -> m ((a -> m a) -> m a)
forall (m :: * -> *) (field :: (* -> *) -> * -> * -> *) record a.
(Monad m, FieldGet field) =>
field m record a -> record -> m a
get Field m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this(Var m ((a -> m a) -> m a) -> m ((a -> m a) -> m a))
-> (record -> Var m ((a -> m a) -> m a))
-> record
-> m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> m a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef(MFieldRef m a -> Var m ((a -> m a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
field (record -> m ((a -> m a) -> m a))
-> record -> m ((a -> m a) -> m a)
forall a b. (a -> b) -> a -> b
$ record
record; (a -> m a) -> m a
mm a -> m a
go

instance FieldSwitch MField
  where
    switchRecord :: MField m record a -> record -> Int -> m ()
switchRecord MField m record a
field record
record = m a -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void(m a -> m ()) -> (Int -> m a) -> Int -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MField m record a -> record -> (a -> a) -> m a
forall (field :: (* -> *) -> * -> * -> *) (m :: * -> *) record a.
(FieldModify field, Monad m) =>
field m record a -> record -> (a -> a) -> m a
modifyRecord MField m record a
field record
record((a -> a) -> m a) -> (Int -> a -> a) -> Int -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Int -> a -> a
forall switch. IsSwitch switch => Int -> switch -> switch
toggle

--------------------------------------------------------------------------------

class IsRef ref
  where
    -- | Create new reference to the given variable.
    link :: (MonadVar m) => Var m a -> m (ref m a)
    
    -- | Get an associated 'MFieldRef' reference to the given reference.
    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 = MFieldRef
  {
    MFieldRef m a -> Var m (m a)
getRef     :: !(Var m (m a)),
    MFieldRef m a -> Var m (a -> m ())
setRef     :: !(Var m (a -> m ())),
    MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef  :: !(Var m ((a -> a) -> m a)),
    MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef :: !(Var m ((a -> m a) -> m a))
  } deriving ( Typeable )

instance IsRef MFieldRef
  where
    ref :: MFieldRef m a -> MFieldRef m a
ref    = MFieldRef m a -> MFieldRef m a
forall a. a -> a
id
    link :: Var m a -> m (MFieldRef m a)
link Var m a
x = (Var m (m a)
 -> Var m (a -> m ())
 -> Var m ((a -> a) -> m a)
 -> Var m ((a -> m a) -> m a)
 -> MFieldRef m a)
-> m (Var m (m a))
-> m (Var m (a -> m ()))
-> m (Var m ((a -> a) -> m a))
-> m (Var m ((a -> m a) -> m a))
-> m (MFieldRef m a)
forall (m :: * -> *) a1 a2 a3 a4 r.
Monad m =>
(a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
liftM4 Var m (m a)
-> Var m (a -> m ())
-> Var m ((a -> a) -> m a)
-> Var m ((a -> m a) -> m a)
-> MFieldRef m a
forall (m :: * -> *) a.
Var m (m a)
-> Var m (a -> m ())
-> Var m ((a -> a) -> m a)
-> Var m ((a -> m a) -> m a)
-> MFieldRef m a
MFieldRef (m a -> m (Var m (m a))
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
a -> m (var a)
var (GetterFor m (Var m a) a
forall a. GetterFor m (Var m a) a
g Var m a
x)) ((a -> m ()) -> m (Var m (a -> m ()))
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
a -> m (var a)
var (SetterFor m (Var m a) a
forall a. SetterFor m (Var m a) a
s Var m a
x)) (((a -> a) -> m a) -> m (Var m ((a -> a) -> m a))
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
a -> m (var a)
var (ModifierFor m (Var m a) a
forall a. ModifierFor m (Var m a) a
m Var m a
x)) (((a -> m a) -> m a) -> m (Var m ((a -> m a) -> m a))
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
a -> m (var a)
var (ModifierMFor m (Var m a) a
forall a. ModifierMFor m (Var m a) a
mm Var m a
x))
      where
        Field GetterFor m (Var m a) a
g SetterFor m (Var m a) a
s ModifierFor m (Var m a) a
m ModifierMFor m (Var m a) a
mm = Field m (Var m a) a
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this

getter :: MField m record a -> Field m record (m a)
getter :: MField m record a -> Field m record (m a)
getter (MField record -> MFieldRef m a
f) =
  let Field GetterFor m (Var m a) a
g SetterFor m (Var m a) a
s ModifierFor m (Var m a) a
m ModifierMFor m (Var m a) a
mm = Field m (Var m a) a
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this
  in  GetterFor m record (m a)
-> SetterFor m record (m a)
-> ModifierFor m record (m a)
-> ModifierMFor m record (m a)
-> Field m record (m a)
forall (m :: * -> *) record a.
GetterFor m record a
-> SetterFor m record a
-> ModifierFor m record a
-> ModifierMFor m record a
-> Field m record a
Field (GetterFor m (Var m (m a)) (m a)
forall a. GetterFor m (Var m a) a
gGetterFor m (Var m (m a)) (m a)
-> (record -> Var m (m a)) -> GetterFor m record (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m (m a)
getRef(MFieldRef m a -> Var m (m a))
-> (record -> MFieldRef m a) -> record -> Var m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (SetterFor m (Var m (m a)) (m a)
forall a. SetterFor m (Var m a) a
sSetterFor m (Var m (m a)) (m a)
-> (record -> Var m (m a)) -> SetterFor m record (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m (m a)
getRef(MFieldRef m a -> Var m (m a))
-> (record -> MFieldRef m a) -> record -> Var m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierFor m (Var m (m a)) (m a)
forall a. ModifierFor m (Var m a) a
mModifierFor m (Var m (m a)) (m a)
-> (record -> Var m (m a)) -> ModifierFor m record (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m (m a)
getRef(MFieldRef m a -> Var m (m a))
-> (record -> MFieldRef m a) -> record -> Var m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierMFor m (Var m (m a)) (m a)
forall a. ModifierMFor m (Var m a) a
mmModifierMFor m (Var m (m a)) (m a)
-> (record -> Var m (m a)) -> ModifierMFor m record (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m (m a)
getRef(MFieldRef m a -> Var m (m a))
-> (record -> MFieldRef m a) -> record -> Var m (m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f)

setter :: MField m record a -> Field m record (a -> m ())
setter :: MField m record a -> Field m record (a -> m ())
setter (MField record -> MFieldRef m a
f) =
  let Field GetterFor m (Var m a) a
g SetterFor m (Var m a) a
s ModifierFor m (Var m a) a
m ModifierMFor m (Var m a) a
mm = Field m (Var m a) a
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this
  in  GetterFor m record (a -> m ())
-> SetterFor m record (a -> m ())
-> ModifierFor m record (a -> m ())
-> ModifierMFor m record (a -> m ())
-> Field m record (a -> m ())
forall (m :: * -> *) record a.
GetterFor m record a
-> SetterFor m record a
-> ModifierFor m record a
-> ModifierMFor m record a
-> Field m record a
Field (GetterFor m (Var m (a -> m ())) (a -> m ())
forall a. GetterFor m (Var m a) a
gGetterFor m (Var m (a -> m ())) (a -> m ())
-> (record -> Var m (a -> m ())) -> GetterFor m record (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (a -> m ())
forall (m :: * -> *) a. MFieldRef m a -> Var m (a -> m ())
setRef(MFieldRef m a -> Var m (a -> m ()))
-> (record -> MFieldRef m a) -> record -> Var m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (SetterFor m (Var m (a -> m ())) (a -> m ())
forall a. SetterFor m (Var m a) a
sSetterFor m (Var m (a -> m ())) (a -> m ())
-> (record -> Var m (a -> m ())) -> SetterFor m record (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (a -> m ())
forall (m :: * -> *) a. MFieldRef m a -> Var m (a -> m ())
setRef(MFieldRef m a -> Var m (a -> m ()))
-> (record -> MFieldRef m a) -> record -> Var m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierFor m (Var m (a -> m ())) (a -> m ())
forall a. ModifierFor m (Var m a) a
mModifierFor m (Var m (a -> m ())) (a -> m ())
-> (record -> Var m (a -> m ()))
-> ModifierFor m record (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (a -> m ())
forall (m :: * -> *) a. MFieldRef m a -> Var m (a -> m ())
setRef(MFieldRef m a -> Var m (a -> m ()))
-> (record -> MFieldRef m a) -> record -> Var m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierMFor m (Var m (a -> m ())) (a -> m ())
forall a. ModifierMFor m (Var m a) a
mmModifierMFor m (Var m (a -> m ())) (a -> m ())
-> (record -> Var m (a -> m ()))
-> ModifierMFor m record (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m (a -> m ())
forall (m :: * -> *) a. MFieldRef m a -> Var m (a -> m ())
setRef(MFieldRef m a -> Var m (a -> m ()))
-> (record -> MFieldRef m a) -> record -> Var m (a -> m ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f)

modifier :: MField m record a -> Field m record ((a -> a) -> m a)
modifier :: MField m record a -> Field m record ((a -> a) -> m a)
modifier (MField record -> MFieldRef m a
f) =
  let Field GetterFor m (Var m a) a
g SetterFor m (Var m a) a
s ModifierFor m (Var m a) a
m ModifierMFor m (Var m a) a
mm = Field m (Var m a) a
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this
  in  GetterFor m record ((a -> a) -> m a)
-> SetterFor m record ((a -> a) -> m a)
-> ModifierFor m record ((a -> a) -> m a)
-> ModifierMFor m record ((a -> a) -> m a)
-> Field m record ((a -> a) -> m a)
forall (m :: * -> *) record a.
GetterFor m record a
-> SetterFor m record a
-> ModifierFor m record a
-> ModifierMFor m record a
-> Field m record a
Field (GetterFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
forall a. GetterFor m (Var m a) a
gGetterFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
-> (record -> Var m ((a -> a) -> m a))
-> GetterFor m record ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef(MFieldRef m a -> Var m ((a -> a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (SetterFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
forall a. SetterFor m (Var m a) a
sSetterFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
-> (record -> Var m ((a -> a) -> m a))
-> SetterFor m record ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef(MFieldRef m a -> Var m ((a -> a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
forall a. ModifierFor m (Var m a) a
mModifierFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
-> (record -> Var m ((a -> a) -> m a))
-> ModifierFor m record ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef(MFieldRef m a -> Var m ((a -> a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierMFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
forall a. ModifierMFor m (Var m a) a
mmModifierMFor m (Var m ((a -> a) -> m a)) ((a -> a) -> m a)
-> (record -> Var m ((a -> a) -> m a))
-> ModifierMFor m record ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> a) -> m a)
modifyRef(MFieldRef m a -> Var m ((a -> a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f)

modifierM :: MField m record a -> Field m record ((a -> m a) -> m a)
modifierM :: MField m record a -> Field m record ((a -> m a) -> m a)
modifierM (MField record -> MFieldRef m a
f) =
  let Field GetterFor m (Var m a) a
g SetterFor m (Var m a) a
s ModifierFor m (Var m a) a
m ModifierMFor m (Var m a) a
mm = Field m (Var m a) a
forall (m :: * -> *) (var :: * -> *) a.
IsMVar m var =>
Field m (var a) a
this
  in  GetterFor m record ((a -> m a) -> m a)
-> SetterFor m record ((a -> m a) -> m a)
-> ModifierFor m record ((a -> m a) -> m a)
-> ModifierMFor m record ((a -> m a) -> m a)
-> Field m record ((a -> m a) -> m a)
forall (m :: * -> *) record a.
GetterFor m record a
-> SetterFor m record a
-> ModifierFor m record a
-> ModifierMFor m record a
-> Field m record a
Field (GetterFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
forall a. GetterFor m (Var m a) a
gGetterFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
-> (record -> Var m ((a -> m a) -> m a))
-> GetterFor m record ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> m a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef(MFieldRef m a -> Var m ((a -> m a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (SetterFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
forall a. SetterFor m (Var m a) a
sSetterFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
-> (record -> Var m ((a -> m a) -> m a))
-> SetterFor m record ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> m a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef(MFieldRef m a -> Var m ((a -> m a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
forall a. ModifierFor m (Var m a) a
mModifierFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
-> (record -> Var m ((a -> m a) -> m a))
-> ModifierFor m record ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> m a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef(MFieldRef m a -> Var m ((a -> m a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f) (ModifierMFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
forall a. ModifierMFor m (Var m a) a
mmModifierMFor m (Var m ((a -> m a) -> m a)) ((a -> m a) -> m a)
-> (record -> Var m ((a -> m a) -> m a))
-> ModifierMFor m record ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.MFieldRef m a -> Var m ((a -> m a) -> m a)
forall (m :: * -> *) a. MFieldRef m a -> Var m ((a -> m a) -> m a)
modifyMRef(MFieldRef m a -> Var m ((a -> m a) -> m a))
-> (record -> MFieldRef m a) -> record -> Var m ((a -> m a) -> m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.record -> MFieldRef m a
f)

--------------------------------------------------------------------------------

-- | 'MFieldRep' is a helper type that stores a variable and its accessors.
data MFieldRep m a = MFieldRep !(Var m a) {-# UNPACK #-} !(MFieldRef m a)
  deriving ( Typeable )

instance IsRef MFieldRep
  where
    link :: Var m a -> m (MFieldRep m a)
link Var m a
x = Var m a -> MFieldRef m a -> MFieldRep m a
forall (m :: * -> *) a. Var m a -> MFieldRef m a -> MFieldRep m a
MFieldRep Var m a
x (MFieldRef m a -> MFieldRep m a)
-> m (MFieldRef m a) -> m (MFieldRep m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Var m a -> m (MFieldRef m a)
forall (ref :: (* -> *) -> * -> *) (m :: * -> *) a.
(IsRef ref, MonadVar m) =>
Var m a -> m (ref m a)
link Var m a
x
    ref :: MFieldRep m a -> MFieldRef m a
ref (MFieldRep Var m a
_ MFieldRef m a
fr) = MFieldRef m a
fr