<commit_before>{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnicodeSyntax #-}

{-| There are several tasks for which a user may wish to use the Visitor
    package, such as gathering up all the results in a tree and stopping as soon
    as the first result is found.  Because almost all of the infrastructure
    required for these different modes is the same, rather than creating a
    different system for each mode we instead re-use the same system but pass
    around a mode parameter that dictates its behavior at various points as well
    as some of the types in the system.

    The implementation of the 'VisitorMode' uses a GADT where each constructor
    causes 'VisitorMode' to have a different type parameter;  this was done so
    that pattern matching can be used when the specific mode matters and also
    type families can be used to specialized types depending on the constructor.
 -}
module Visitor.Parallel.Common.VisitorMode
    (
    -- * Types
      VisitorMode(..)
    , AllMode(..)
    , FirstMode(..)
    , FoundModeUsingPull(..)
    , FoundModeUsingPush(..)
    -- * Type-classes
    , HasVisitorMode(..)
    -- * Type families
    , ResultFor
    , ProgressFor
    , FinalResultFor
    , WorkerIntermediateValueFor
    , WorkerFinalProgressFor
    -- * Functions
    , checkpointFromIntermediateProgress
    , initialProgress
    , initialWorkerIntermediateValue
    ) where


import Data.Monoid

import Visitor.Checkpoint

--------------------------------------------------------------------------------
------------------------------------ Types -------------------------------------
--------------------------------------------------------------------------------

{-| A type indicating the mode in which the visiting is being run.  Note that
    this is a GADT for which the type parameter is unique to each constructor
    in order to allow types to be specialized.

    Unfortunately Haddock does not seem to support documenting the constructors
    of a GADT, so for the documentation for each constructor refer to the types
    used to tag them, defined after the 'VisitorMode' type.
 -}
data VisitorMode visitor_mode where
    AllMode :: Monoid result ⇒ VisitorMode (AllMode result)
    FirstMode :: VisitorMode (FirstMode result)
    FoundModeUsingPull :: Monoid result ⇒ (result → Maybe final_result) → VisitorMode (FoundModeUsingPull result final_result)
    FoundModeUsingPush :: Monoid result ⇒ (result → Maybe final_result) → VisitorMode (FoundModeUsingPush result final_result)

{-| Visit all nodes and sum the results in all of the leaves. -}
data AllMode result
{-| Visit nodes until a result is found, and if so then stop. -}
data FirstMode result
{-| Visit nodes, summing their results, until a condition has been met, and if
    so stop and return the condition's result; "Pull" means that each worker's
    results will be kept and summed locally until a request for them has been
    received from the supervisor.
 -}
data FoundModeUsingPull result final_result
{-| Same as 'FoundModeUsingPull', but pushes each result to thesupervisor as it
    is found rather than summing them in the worker until they are requested by
    the supervisor.
 -}
data FoundModeUsingPush result final_result

--------------------------------------------------------------------------------
--------------------------------- Type-classes ---------------------------------
--------------------------------------------------------------------------------

{-| This class indicates that a monad has information about the current visitor
    mode tag type that can be extracted from it.
 -}
class HasVisitorMode (monad :: * → *) where
    type VisitorModeFor monad :: *

--------------------------------------------------------------------------------
-------------------------------- Type families ---------------------------------
--------------------------------------------------------------------------------

{- $families<commit_msg>Beefed up some of the visitor mode documentation.<commit_after>{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnicodeSyntax #-}

{-| There are several tasks for which a user may wish to use the Visitor
    package, such as gathering up all the results in a tree and stopping as soon
    as the first result is found.  Because almost all of the infrastructure
    required for these different modes is the same, rather than creating a
    different system for each mode we instead re-use the same system but pass
    around a mode parameter that dictates its behavior at various points as well
    as some of the types in the system.

    The implementation of the 'VisitorMode' uses a GADT where each constructor
    causes 'VisitorMode' to have a different type parameter;  this was done so
    that pattern matching can be used when the specific mode matters and also
    type families can be used to specialized types depending on the constructor.
 -}
module Visitor.Parallel.Common.VisitorMode
    (
    -- * Types
      VisitorMode(..)
    , AllMode(..)
    , FirstMode(..)
    , FoundModeUsingPull(..)
    , FoundModeUsingPush(..)
    -- * Type-classes
    , HasVisitorMode(..)
    -- * Type families
    , ResultFor
    , ProgressFor
    , FinalResultFor
    , WorkerIntermediateValueFor
    , WorkerFinalProgressFor
    -- * Functions
    , checkpointFromIntermediateProgress
    , initialProgress
    , initialWorkerIntermediateValue
    ) where


import Data.Monoid

import Visitor.Checkpoint

--------------------------------------------------------------------------------
------------------------------------ Types -------------------------------------
--------------------------------------------------------------------------------

{-| A type indicating the mode in which the visiting is being run.  Note that
    this is a GADT for which the type parameter is unique to each constructor
    in order to allow types to be specialized.

    Unfortunately Haddock does not seem to support documenting the constructors
    of a GADT, so for the documentation for each constructor refer to the types
    used to tag them, defined after the 'VisitorMode' type.
 -}
data VisitorMode visitor_mode where
    AllMode :: Monoid result ⇒ VisitorMode (AllMode result)
    FirstMode :: VisitorMode (FirstMode result)
    FoundModeUsingPull :: Monoid result ⇒ (result → Maybe final_result) → VisitorMode (FoundModeUsingPull result final_result)
    FoundModeUsingPush :: Monoid result ⇒ (result → Maybe final_result) → VisitorMode (FoundModeUsingPush result final_result)

{-| Visit all nodes and sum the results in all of the leaves. -}
data AllMode result
{-| Visit nodes until a result is found, and if so then stop. -}
data FirstMode result
{-| Visit nodes, summing their results, until a condition has been met, and if
    so stop and return the condition's result; `Pull` means that each worker's
    results will be kept and summed locally until a request for them has been
    received from the supervisor, which means that there might be a period of
    time where the collectively found results meet the condition but the system
    is unaware of this as they are scattered amongst the workerss.
 -}
data FoundModeUsingPull result final_result
{-| Same as 'FoundModeUsingPull', but pushes each result to the supervisor as it
    is found rather than summing them in the worker until they are requested by
    the supervisor, which guarantees that the system will recognize when the
    condition has been met as soon as final result needed was found but has the
    downside that if there are a large number of results needed then sending
    each one could be much more costly then summing them locally and sending the
    current total on a regular basis to the supervisor.
 -}
data FoundModeUsingPush result final_result

--------------------------------------------------------------------------------
--------------------------------- Type-classes ---------------------------------
--------------------------------------------------------------------------------

{-| This class indicates that a monad has information about the current visitor
    mode tag type that can be extracted from it.
 -}
class HasVisitorMode (monad :: * → *) where
    type VisitorModeFor monad :: *

--------------------------------------------------------------------------------
-------------------------------- Type families ---------------------------------
--------------------------------------------------------------------------------

{- $families
{'fraction_non_alphanumeric': 0.20399591327051877, 'fraction_numerical': 0.00022704052673402204, 'mean_word_length': 1.89612097304405, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5099257', 'n_tokens_mistral': 2024, 'n_tokens_neox': 1968, 'n_words': 955}