\begin{code} {-# OPTIONS --safe --cubical #-} module Data.List.Kleene where open import Prelude open import Data.Fin mutual infixr 5 _&_ ∹_ infixl 5 _⁺ _⋆ \end{code} %<*plus-def> \begin{code} record _⁺ (A : Type a) : Type a where inductive constructor _&_ field head : A tail : A ⋆ \end{code} %</plus-def> %<*star-def> \begin{code} data _⋆ (A : Type a) : Type a where [] : A ⋆ ∹_ : A ⁺ → A ⋆ \end{code} %</star-def> \begin{code} open _⁺ public mutual foldr⁺ : (A → B → B) → B → A ⁺ → B foldr⁺ f b (x & xs) = f x (foldr⋆ f b xs) foldr⋆ : (A → B → B) → B → A ⋆ → B foldr⋆ f b [] = b foldr⋆ f b (∹ xs) = foldr⁺ f b xs length⋆ : A ⋆ → ℕ length⋆ = foldr⋆ (const suc) zero length⁺ : A ⁺ → ℕ length⁺ = foldr⁺ (const suc) zero mutual _!⁺_ : (xs : A ⁺) → Fin (length⁺ xs) → A xs !⁺ f0 = xs .head xs !⁺ fs i = xs .tail !⋆ i _!⋆_ : (xs : A ⋆) → Fin (length⋆ xs) → A (∹ xs) !⋆ i = xs !⁺ i map⋆ : (A → B) → A ⋆ → B ⋆ map⋆ f = foldr⋆ (λ x xs → ∹ f x & xs) [] map⁺ : (A → B) → A ⁺ → B ⁺ map⁺ f (x & xs) = f x & map⋆ f xs mutual _⋆++⋆_ : A ⋆ → A ⋆ → A ⋆ [] ⋆++⋆ ys = ys (∹ xs) ⋆++⋆ ys = ∹ (xs ⁺++⋆ ys) _⁺++⋆_ : A ⁺ → A ⋆ → A ⁺ head (xs ⁺++⋆ ys) = head xs tail (xs ⁺++⋆ ys) = tail xs ⋆++⋆ ys \end{code}