Safe Haskell | None |
---|---|
Language | Haskell98 |
A monad for working with game trees.
- class (Functor go, Applicative go, Monad go) => MonadGo go where
- getCursor :: go Cursor
- getCoordState :: Coord -> go CoordState
- goUp :: go Bool
- goDown :: Int -> go Bool
- goLeft :: go Bool
- goRight :: go Bool
- goToRoot :: go ()
- goToGameInfoNode :: Bool -> go Bool
- pushPosition :: go ()
- popPosition :: go ()
- dropPosition :: go ()
- getProperties :: go [Property]
- modifyProperties :: ([Property] -> [Property]) -> go ()
- getProperty :: Descriptor d => d -> go (Maybe Property)
- getPropertyValue :: ValuedDescriptor v d => d -> go (Maybe v)
- putProperty :: Property -> go ()
- deleteProperty :: Descriptor d => d -> go ()
- modifyProperty :: Descriptor d => d -> (Maybe Property -> Maybe Property) -> go ()
- modifyPropertyValue :: ValuedDescriptor v d => d -> (Maybe v -> Maybe v) -> go ()
- modifyPropertyString :: (Stringlike s, ValuedDescriptor s d) => d -> (String -> String) -> go ()
- modifyPropertyList :: ValuedDescriptor [v] d => d -> ([v] -> [v]) -> go ()
- modifyPropertyCoords :: ValuedDescriptor CoordList d => d -> ([Coord] -> [Coord]) -> go ()
- modifyGameInfo :: (GameInfo -> GameInfo) -> go GameInfo
- modifyVariationMode :: (VariationMode -> VariationMode) -> go ()
- getAssignedStone :: Coord -> go (Maybe (Maybe Color))
- getAllAssignedStones :: go (Map Coord (Maybe Color))
- modifyAssignedStones :: [Coord] -> (Maybe (Maybe Color) -> Maybe (Maybe Color)) -> go ()
- getMark :: Coord -> go (Maybe Mark)
- modifyMark :: (Maybe Mark -> Maybe Mark) -> Coord -> go ()
- addChild :: Node -> go ()
- addChildAt :: Int -> Node -> go ()
- deleteChildAt :: Int -> go NodeDeleteResult
- on :: Event go h -> h -> go ()
- on0 :: Event go h -> go () -> go ()
- data GoT m a
- type GoM = GoT Identity
- runGoT :: Monad m => GoT m a -> Cursor -> m (a, Cursor)
- runGo :: GoM a -> Cursor -> (a, Cursor)
- evalGoT :: Monad m => GoT m a -> Cursor -> m a
- evalGo :: GoM a -> Cursor -> a
- execGoT :: Monad m => GoT m a -> Cursor -> m Cursor
- execGo :: GoM a -> Cursor -> Cursor
- data Step
- data NodeDeleteResult
- data Event go h
- data AnyEvent go = forall h . AnyEvent (Event go h)
- eventName :: Event go h -> String
- fire :: Monad m => Event (GoT m) h -> (h -> GoT m ()) -> GoT m ()
- eventHandlerFromAction :: Event go h -> go () -> h
- childAddedEvent :: Event go (ChildAddedHandler go)
- type ChildAddedHandler go = Int -> go ()
- childDeletedEvent :: Event go (ChildDeletedHandler go)
- type ChildDeletedHandler go = Cursor -> go ()
- gameInfoChangedEvent :: Event go (GameInfoChangedHandler go)
- type GameInfoChangedHandler go = GameInfo -> GameInfo -> go ()
- navigationEvent :: Event go (NavigationHandler go)
- type NavigationHandler go = Step -> go ()
- propertiesModifiedEvent :: Event go (PropertiesModifiedHandler go)
- type PropertiesModifiedHandler go = [Property] -> [Property] -> go ()
- variationModeChangedEvent :: Event go (VariationModeChangedHandler go)
- type VariationModeChangedHandler go = VariationMode -> VariationMode -> go ()
The Go monad
class (Functor go, Applicative go, Monad go) => MonadGo go where Source
A monad (transformer) for navigating and mutating Cursor
s, and
remembering previous locations. See GoT
and GoM
.
The monad supports handlers for events raised during actions it takes, such as navigating through the tree and modifying nodes.
getCursor, goUp, goDown, goLeft, goRight, goToRoot, goToGameInfoNode, pushPosition, popPosition, dropPosition, modifyProperties, getProperty, modifyProperty, modifyGameInfo, modifyVariationMode, addChildAt, deleteChildAt, on
Returns the current cursor.
getCoordState :: Coord -> go CoordState Source
Returns the CoordState
at the given point.
Navigates up to the parent node, fires a navigationEvent
, then returns
true. If already at the root of the tree, then none of this happens and
false is returned.
goDown :: Int -> go Bool Source
Navigates down the tree to the child with the given index, fires a
navigationEvent
, then returns true. If the requested child doesn't
exist, then none of this happens and false is returned.
If possible, moves to the sibling node immediately to the left of the
current one. Returns whether a move was made (i.e. whether there was a
left sibling). Fires navigationEvent
s while moving.
If possible, moves to the sibling node immediately to the right of the
current one. Returns whether a move was made (i.e. whether there was a
right sibling). Fires navigationEvent
s while moving.
Navigates up to the root of the tree. Fires navigationEvent
s for each
step.
:: Bool | When no node with game info is found, then if false, return to the original node, otherwise finish at the root node. |
-> go Bool |
Navigates up the tree to the node containing game info properties, if any. Returns true if a game info node was found.
pushPosition :: go () Source
Pushes the current location in the game tree onto an internal position
stack, such that popPosition
is capable of navigating back to the same
position, even if the game tree has been modified (though the old position
must still exist in the tree to return to it).
popPosition :: go () Source
Returns to the last position pushed onto the internal position stack via
pushPosition
. This action must be balanced by a pushPosition
.
dropPosition :: go () Source
Drops the last position pushed onto the internal stack by pushPosition
off of the stack. This action must be balanced by a pushPosition
.
getProperties :: go [Property] Source
Returns the set of properties on the current node.
modifyProperties :: ([Property] -> [Property]) -> go () Source
Modifies the set of properties on the current node. Fires
propertiesModifiedEvent
after modifying if the new property set is
different from the old property set (order is irrelevant).
getProperty :: Descriptor d => d -> go (Maybe Property) Source
Searches for a property on the current node, returning it if found.
getPropertyValue :: ValuedDescriptor v d => d -> go (Maybe v) Source
Searches for a valued property on the current node, returning its value if found.
putProperty :: Property -> go () Source
Sets a property on the current node, replacing an existing property with
the same name, if one exists. Fires propertiesModifiedEvent
if the
property has changed.
deleteProperty :: Descriptor d => d -> go () Source
Deletes a property from the current node, if it's set, and fires
propertiesModifiedEvent
.
Note that although a Property
is a Descriptor
, giving a valued
Property
here will not cause deletion to match on the value of the
property. That is, the following code will result in Nothing
, because
the deletion only cares about the name of the property.
do putProperty $ PL Black deleteProperty $ PL White getPropertyValue propertyPL
modifyProperty :: Descriptor d => d -> (Maybe Property -> Maybe Property) -> go () Source
Calls the given function to modify the state of the given property
(descriptor) on the current node. Nothing
represents the property not
existing on the node, and a Just
marks the property's presence. Fires
propertiesModifiedEvent
if the property changed. This function does not
do any validation to check that the resulting tree state is valid.
modifyPropertyValue :: ValuedDescriptor v d => d -> (Maybe v -> Maybe v) -> go () Source
Calls the given function to modify the state of the given valued property
(descriptor) on the current node. Nothing
represents the property not
existing on the node, and a Just
with the property's value marks the
property's presence. Fires propertiesModifiedEvent
if the property
changed. This function does not do any validation to check that the
resulting tree state is valid.
modifyPropertyString :: (Stringlike s, ValuedDescriptor s d) => d -> (String -> String) -> go () Source
Mutates the string-valued property attached to the current node according
to the given function. The input string will be empty if the current node
either has the property with an empty value, or doesn't have the property.
Returning an empty string removes the property from the node, if it was
set. Fires propertiesModifiedEvent
if the property changed.
modifyPropertyList :: ValuedDescriptor [v] d => d -> ([v] -> [v]) -> go () Source
Mutates the list-valued property attached to the current node according to the given function. The input list will be empty if the current node either has the property with an empty value, or doesn't have the property. Returning an empty list removes the property from the node, if it was set.
Fires propertiesModifiedEvent
if the property changed.
See also modifyPropertyCoords
.
modifyPropertyCoords :: ValuedDescriptor CoordList d => d -> ([Coord] -> [Coord]) -> go () Source
Mutates the CoordList
-valued property attached to the current node
according to the given function. Conversion between CoordList
and
[Coord]
is performed automatically. The input list will be empty if the
current node either has the property with an empty value, or doesn't have
the property. Returning an empty list removes the property from the node,
if it was set.
Importantly, this might not be specific enough for properties such as DD
and VW
where a present, empty list has different semantics from the
property not being present. In that case, modifyPropertyValue
is better.
Fires propertiesModifiedEvent
if the property changed.
modifyGameInfo :: (GameInfo -> GameInfo) -> go GameInfo Source
Mutates the game info for the current path, returning the new info. If the current node or one of its ancestors has game info properties, then that node is modified. Otherwise, properties are inserted on the root node.
modifyVariationMode :: (VariationMode -> VariationMode) -> go () Source
Sets the game's VariationMode
via the ST
property on the root node,
then fires a variationModeChangedEvent
if the variation mode has changed.
getAssignedStone :: Coord -> go (Maybe (Maybe Color)) Source
Retrieves the stone assigned in the current node to a point by AB
,
AE
, or AW
. The possible results are:
Nothing
: No stone has been assigned to the point. The point could still be in any state, e.g. from a play on the current node or some property in an ancestor node.Just Nothing
: The point has been assigned to be empty.Just (Just Color)
: The point has been assigned to have a stone of the given color.
getAllAssignedStones :: go (Map Coord (Maybe Color)) Source
Looks up all stones that are assigned by AB
, AE
, or AW
properties
on the current node. Returns a map from each point to the stone that is
assigned to the point.
modifyAssignedStones :: [Coord] -> (Maybe (Maybe Color) -> Maybe (Maybe Color)) -> go () Source
Modifies the state of currently assigned stones, keeping in mind that it
is invalid to mix MoveProperty
and SetupProperty
properties in a single
node. This function has the behaviour of a user changing stone assignments
in a UI. How this function works is:
- Pick a node to work with. If there is a move property on the current node and there is not already a setup property on the current node, then we'll create and modify a new child node. Otherwise, either there are no move properties on the node (so we can add setup properties at will), or there are both move and setup properties on the node (the node is already invalid), so we'll just modify the current node.
- If we're modifying the current node, then apply the modification function
to the state of stone assignment for each coordinate. See
getAssignedStone
for the meaning ofMaybe (Maybe Color)
. Modify the properties in the node as necessary to apply the result (propertiesModifiedEvent
). (NOTE: Currently one event is fired for each property modified; this may change in the future.) - If we need to create a child node, then apply the modification function
to
Nothing
to determine if we're actually adding assignments. If the function returns aJust
, then we create a child node with the necessary assignment properties, insert it (childAddedEvent
), then navigate to it (navigationEvent
). If the function returnsNothing
, thenmodifyAssignedStones
does nothing.
getMark :: Coord -> go (Maybe Mark) Source
Returns the Mark
at a point on the current node.
modifyMark :: (Maybe Mark -> Maybe Mark) -> Coord -> go () Source
Calls the given function to modify the presence of a Mark
on the
current node.
addChild :: Node -> go () Source
Adds a child node to the current node at the end of the current node's
child list. Fires a childAddedEvent
after the child is added.
addChildAt :: Int -> Node -> go () Source
Adds a child node to the current node at the given index, shifting all
existing children at and after the index to the right. The index must be
in the range [0, numberOfChildren]
. Fires a childAddedEvent
after the
child is added.
deleteChildAt :: Int -> go NodeDeleteResult Source
Tries to remove the child node at the given index below the current node. Returns a status code indicating whether the deletion succeeded, or why not.
on :: Event go h -> h -> go () Source
Registers a new event handler for a given event type.
on0 :: Event go h -> go () -> go () Source
Registers a new event handler for a given event type. Unlike on
, whose
handler may receive arguments, the handler given here doesn't receive any
arguments.
The standard monad transformer for MonadGo
.
MonadTrans GoT | |
MonadState s m => MonadState s (GoT m) | |
MonadWriter w m => MonadWriter w (GoT m) | |
Monad m => Monad (GoT m) | |
Monad m => Functor (GoT m) | |
Monad m => Applicative (GoT m) | |
MonadIO m => MonadIO (GoT m) | |
Monad m => MonadGo (GoT m) |
runGoT :: Monad m => GoT m a -> Cursor -> m (a, Cursor) Source
Executes a Go monad transformer on a cursor, returning in the underlying monad a tuple that contains the resulting value and the final cursor.
evalGoT :: Monad m => GoT m a -> Cursor -> m a Source
Executes a Go monad transformer on a cursor, returning in the underlying monad the value in the transformer.
evalGo :: GoM a -> Cursor -> a Source
Runs a Go monad on a cursor and returns the value in the monad.
execGoT :: Monad m => GoT m a -> Cursor -> m Cursor Source
Executes a Go monad transformer on a cursor, returning in the underlying monad the final cursor.
A single step along a game tree. Either up or down.
data NodeDeleteResult Source
The result of deleting a node.
NodeDeleteOk | The node was deleted successfully. |
NodeDeleteBadIndex | The node couldn't be deleted, because an invalid index was given. |
NodeDeleteOnPathStack | The node couldn't be deleted, because it is on the path stack. |
Event handling
A type of event in a Go monad that can be handled by executing an action.
go
is the type of the Go monad. h
is the handler type, a function that
takes some arguments relating to the event and returns an action in the Go
monad. The arguments to the handler are usually things that would be
difficult to recover from the state of the monad alone, for example the
Step
associated with a navigationEvent
.
The Eq
, Ord
, and Show
instances use events' names, via eventName
.
fire :: Monad m => Event (GoT m) h -> (h -> GoT m ()) -> GoT m () Source
Fires all of the handlers for the given event, using the given function to create a Go action from each of the handlers (normally themselves functions that create Go actions, if they're not just Go actions directly, depending on the event).
eventHandlerFromAction :: Event go h -> go () -> h Source
Events
childAddedEvent :: Event go (ChildAddedHandler go) Source
An event corresponding to a child node being added to the current node.
type ChildAddedHandler go = Int -> go () Source
A handler for childAddedEvent
s. Called with the index of the child added
to the current node.
childDeletedEvent :: Event go (ChildDeletedHandler go) Source
An event corresponding to the deletion of one of the current node's children.
type ChildDeletedHandler go = Cursor -> go () Source
A handler for childDeletedEvent
s. It is called with a cursor at the
child that was deleted (this cursor is now out of date).
gameInfoChangedEvent :: Event go (GameInfoChangedHandler go) Source
An event that is fired when the current game info changes, either by navigating past a node with game info properties, or by modifying the current game info properties.
type GameInfoChangedHandler go = GameInfo -> GameInfo -> go () Source
A handler for gameInfoChangedEvent
s. It is called with the old game info
then the new game info.
navigationEvent :: Event go (NavigationHandler go) Source
An event that is fired when a single step up or down in a game tree is made.
type NavigationHandler go = Step -> go () Source
A handler for navigationEvent
s.
A navigation handler may navigate further, but beware infinite recursion. A navigation handler must end on the same node on which it started.
propertiesModifiedEvent :: Event go (PropertiesModifiedHandler go) Source
An event corresponding to a modification to the properties list of the current node.
type PropertiesModifiedHandler go = [Property] -> [Property] -> go () Source
A handler for propertiesModifiedEvent
s. It is called with the old
property list then the new property list.
variationModeChangedEvent :: Event go (VariationModeChangedHandler go) Source
An event corresponding to a change in the active VariationMode
. This can
happen when modifying the ST
property, and also when navigating between
collections (as they have different root nodes).
type VariationModeChangedHandler go = VariationMode -> VariationMode -> go () Source
A handler for variationModeChangedEvent
s. It is called with the old
variation mode then the new variation mode.