content: {-# LANGUAGE DataKinds #-}
  {-# LANGUAGE TypeOperators #-}
  {-# LANGUAGE FlexibleContexts #-}
  
  module Ivory.Stdlib.Operators where
  
  import Ivory.Language
  
  -- | Infix structure field access and dereference.
  -- This is a shorthand for 'deref $ s~>x'.
  (~>*) :: (IvoryVar a, IvoryStruct sym, IvoryRef ref, IvoryStore a,
            IvoryExpr (ref s ('Stored a)),
            IvoryExpr (ref s ('Struct sym))) =>
              ref s ('Struct sym) -> Label sym ('Stored a) -> Ivory eff a
  struct ~>* label = deref (struct~>label)
  infixl 8 ~>*
  
  
  -- | Modify the value stored at a reference by a function.
  (%=) :: IvoryStore a =>
       Ref s ('Stored a) -> (a -> a) -> Ivory eff ()
  ref %= f = do
    val <- deref ref
    store ref (f val)
  
  -- | Modify the value stored at a reference by a function that returns
  -- a value in the Ivory monad
  (%=!) :: IvoryStore a =>
           Ref s ('Stored a) -> (a -> Ivory eff a) -> Ivory eff ()
  ref %=! mf = do
    val  <- deref ref
    val' <- mf val
    store ref val'
  
  -- | Increment the value stored at a reference.
  (+=) :: (Num a, IvoryStore a) =>
          Ref s ('Stored a) -> a -> Ivory eff ()
  ref += x = ref %= (+ x)
  
  