packages feed

zwirn-core-0.1.1.0: src/Zwirn/Core/State.hs

module Zwirn.Core.State where

{-
    State.hs - functions manipulating the underlying state of signals
    Copyright (C) 2025, Martin Gius

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

import Control.Monad.Identity
import qualified Data.Map as Map
import Zwirn.Core.Cord
import Zwirn.Core.Core
import Zwirn.Core.Types

--- functions modifying the state

modify' :: (st -> st) -> ZwirnT k st i a -> ZwirnT k st i a
modify' f x = zwirn $ \t st -> unzwirn x t (f st)

modify :: (MultiMonad k) => (ZwirnT k st i st -> ZwirnT k st i st) -> ZwirnT k st i a -> ZwirnT k st i a
modify f x = set (f (get x)) x

get :: (Applicative k) => ZwirnT k st i a -> ZwirnT k st i st
get = withValueState (\(v, st) -> (fmap (const st) v, st))

set :: (Monad k) => ZwirnT k st i st -> ZwirnT k st i a -> ZwirnT k st i a
set st a = withState . const <$> st <$$> a

-- functions to act on state that is a map

-- | get value of specific key, providing a function in case key is not found
getMap :: (MultiMonad k, Ord key) => (Maybe b -> ZwirnT k (Map.Map key b) i b) -> ZwirnT k (Map.Map key b) i key -> ZwirnT k (Map.Map key b) i b
getMap fromLookup xc = innerJoin $ liftA2 (\k l -> fromLookup $ Map.lookup k l) xc (get (pure ()))

-- | set value of given key
setMap :: (Monad k, Ord key) => ZwirnT k (Map.Map key b) i key -> ZwirnT k (Map.Map key b) i b -> ZwirnT k (Map.Map key b) i a -> ZwirnT k (Map.Map key b) i a
setMap key b = set (liftA2 Map.insert key b <*> get (pure ()))

-- | modify
modifyMap :: (MultiMonad k, Ord key) => (Maybe b -> ZwirnT k (Map.Map key b) i b) -> ZwirnT k (Map.Map key b) i key -> (ZwirnT k (Map.Map key b) i b -> ZwirnT k (Map.Map key b) i b) -> ZwirnT k (Map.Map key b) i a -> ZwirnT k (Map.Map key b) i a
modifyMap fromLookup key f = setMap key (f (getMap fromLookup key))