Fuzion Logo
flang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

state.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation 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, version 3 of the License.
#
# The Fuzion language implementation 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 The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature state
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# state -- represent a state using a monad
#
# this can be used both a plain or as a oneway monad to store a state
# in a way orthogonal to the actual compuation.
#
#
state(

  # types of contained and the state value
  T, S type,

  # the contained value
  val T,

  # the current state
  get S,

  redef r effectMode.val
  ) ref : onewayMonad T (state T S) r
is

  # monadic operator
  #
  redef infix >>= (f T -> state T S) => state.this.bind T f


  # monadic operator
  #
  # Same as non-generic >>=, but also maps to a different type B.
  #
  bind (B type, f T -> state B S) state B S is
    f val


  # return function
  #
  return (a T) => state a get mode


  # map this using f
  #
  map (B type, f T -> B) state B S is
    state (f val) get mode


  # modify the state, leaving the contents unchanged
  #
  modify (f S -> S) => state val (f get) mode


  # set state to new, leaving the contents unchanged
  #
  put (new S) => state val new mode


  # converts option to a string
  #
  # returns the result of $T for an option containing an instance
  # of T, alternatively returns $nil for an option that is nil.
  #
  redef asString string is
    "$val ($get)"


# state with 1 argument is short hand for a state containing unit and
# initialValue
#
state(S type, initialValue S) => state unit initialValue effectMode.plain

# install new state monad for type S and run r within that state monad
#
# return result of r.
#
state(S, R type, initialValue S, r ()->R) =>
  res R := ?
  state unit S unit initialValue (effectMode.inst (()->set res := r.call))
  res


# type related to state declaring features not requiring an instance of state
#
states(T, S type) is


# short-hand for accessing state monad for given type in current environment
#
state_of(S type) => (state unit S).env


# short-hand for getting state monad for given type in current environment
#
state_get(S type) => (state_of S).get


# short-hand for modifying state monad for given type in current environment
#
state_modify(S type, f S->S) => (state_of S).modify f


# short-hand for setting state monad for given type in current environment
#
state_put(S type, new S) => (state_of S).put new