packages feed

moonlight-core-0.1.0.0: src-automata/Moonlight/Automata/Pure/Coalgebra.hs

-- | Top-down duals: folds and annotations flowing from the root, including inherited attributes.
module Moonlight.Automata.Pure.Coalgebra
  ( topDownFold,
    annotateTopDown,
    annotateTopDownWithAttribute,
    projectStateAnnotation,
    projectAttributeAnnotation,
    rootAttribute,
    inheritedAttribute,
  )
where

import Control.Comonad.Cofree (Cofree (..))
import Data.Functor.Foldable (Base, Recursive (project))
import Moonlight.Automata.Pure.Core (TopDownTA (..))
import Prelude

topDownFold :: (Functor f, Recursive t, Base t ~ f) => TopDownTA f state -> (state -> f result -> result) -> state -> t -> result
topDownFold automaton algebra = go
  where
    go state value =
      let distributedChildren = runTopDownTA automaton state (project value)
       in algebra state (fmap (uncurry go) distributedChildren)

annotateTopDown :: (Functor f, Recursive t, Base t ~ f) => TopDownTA f state -> state -> t -> Cofree f state
annotateTopDown automaton =
  topDownFold automaton (\state annotatedChildren -> state :< annotatedChildren)

annotateTopDownWithAttribute :: (Functor f, Recursive t, Base t ~ f) => TopDownTA f state -> (state -> f attribute -> attribute) -> state -> t -> Cofree f (state, attribute)
annotateTopDownWithAttribute automaton algebra =
  topDownFold
    automaton
    ( \state annotatedChildren ->
        let attribute = algebra state (fmap rootAttribute annotatedChildren)
         in (state, attribute) :< annotatedChildren
    )

projectStateAnnotation :: Functor f => Cofree f (state, attribute) -> Cofree f state
projectStateAnnotation = fmap fst

projectAttributeAnnotation :: Functor f => Cofree f (state, attribute) -> Cofree f attribute
projectAttributeAnnotation = fmap snd

rootAttribute :: Cofree f (state, attribute) -> attribute
rootAttribute ((_, attribute) :< _) = attribute

inheritedAttribute :: (Functor f, Recursive t, Base t ~ f) => TopDownTA f state -> (state -> f attribute -> attribute) -> state -> t -> attribute
inheritedAttribute = topDownFold