packages feed

LR-demo-0.0.20251105: src/Saturation.hs

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

module Saturation where

import Control.Monad.Writer (Writer, runWriter, tell)
import Data.Monoid (Any(..))

import DebugPrint

-- Tool box for iteration

type Change = Writer Any

dirty :: Change ()
dirty = tell $ Any True

-- | Iterate until no change.

saturate :: (a -> Change a) -> a -> a
saturate f = loop
  where
  loop x = case runWriter $ f x of
    (y, Any True)  -> loop y
    (y, Any False) -> y

-- | Iterate forever

iterateChange :: (a -> Change a) -> a -> [Change a]
iterateChange f a = iterate (f . fst . runWriter) (dirty >> return a)

-- * Printing

instance DebugPrint a => DebugPrint (Change a) where
  debugPrint w = case runWriter w of
    (a, Any b) -> unwords [ if b then "(dirty)" else "(clean)", debugPrint a ]