Skip to content

Instantly share code, notes, and snippets.

@thelissimus
Created April 12, 2025 01:07
Show Gist options
  • Select an option

  • Save thelissimus/097076bf3751334d7f7850b5e77eef65 to your computer and use it in GitHub Desktop.

Select an option

Save thelissimus/097076bf3751334d7f7850b5e77eef65 to your computer and use it in GitHub Desktop.
Labeling traversables.
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DerivingStrategies #-}
import Control.Monad.State
data Tree a = Node (Tree a) a (Tree a) | Leaf
deriving stock (Show, Functor, Foldable, Traversable)
data Rose a = Rose a [Rose a]
deriving stock (Show, Functor, Foldable, Traversable)
label :: Tree a -> Tree (a, Int)
label = fst . go 0
where
go n = \case
Leaf -> (Leaf, n)
Node lhs val rhs ->
let (lhs', o) = go n lhs
(val', p) = ((val, o), o + 1)
(rhs', q) = go p rhs
in (Node lhs' val' rhs', q)
label' :: Tree a -> Tree (a, Int)
label' t = evalState (traverse f t) 0
where
f x = do
n <- get
put (n + 1)
pure (x, n)
labelTraversable :: (Traversable t) => t a -> t (a, Int)
labelTraversable t = evalState (traverse f t) 0
where
f x = do
n <- get
put (n + 1)
pure (x, n)
foo :: Tree Char
foo = Node Leaf 'a' (Node Leaf 'b' Leaf)
bar :: Rose Char
bar = Rose 'a' [Rose 'b' []]
main :: IO ()
main = do
print (label foo)
print (label' foo)
print (labelTraversable foo)
print (labelTraversable bar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment