Fuzion Logo
fuzion-lang.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 as plain or as a oneway monad to store a state
# in a way orthogonal to the actual computation.
#
#
public state(

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

  # the contained value
  val T,

  # the current state
  get S,

  redef r effect_mode.val
  ) : oneway_monad T (state T S) r
is

  # monadic operator
  #
  public 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.
  #
  public bind (B type, f T -> state B S) state B S =>
    f val


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


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


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


  # set state to new, leaving the contents unchanged
  #
  public 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.
  #
  public redef as_string String =>
    "$val ($get)"


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

# install new state monad for type S and run r within that state monad
#
# return result of r.
#
public state(S, R type, initial_value S, r ()->R) =>
  res option R := nil
  state unit S unit initial_value (effect_mode.inst (()->set res := r.call))
  res.get


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


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


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


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