module Zipper exposing (..) type alias Zipper a = { before : List a , focus : a , after : List a } {- Basic conversion -} fromList : a -> List a -> Zipper a fromList a l = Zipper [] a l toList : Zipper a -> List a toList rl = List.reverse rl.before ++ [rl.focus] ++ rl.after {- Functor like things -} map : (a -> b) -> Zipper a -> Zipper b map f rl = Zipper (List.map f rl.before) (f rl.focus) (List.map f rl.after) edit : (a -> a) -> Zipper a -> Zipper a edit f rl = Zipper rl.before (rl.focus |> f) rl.after {- Comonad functions -} extract : Zipper a -> a extract rl = rl.focus duplicate : Zipper a -> Zipper (Zipper a) duplicate rl = let lefts = iterate1N (List.length rl.before) shiftRight rl rights = iterate1N (List.length rl.after) shiftLeft rl in Zipper lefts rl rights extend : (Zipper a -> b) -> Zipper a -> Zipper b extend f w = map f (duplicate w) (=>>) : Zipper a -> (Zipper a -> b) -> Zipper b (=>>) = flip extend {- Domain functions -} shiftLeft : Zipper a -> Zipper a shiftLeft rl = case rl.after of [] -> case List.reverse rl.before of [] -> Zipper [] rl.focus [] x::xs -> Zipper [rl.focus] x xs x::xs -> Zipper (rl.focus :: rl.before) x xs shiftRight : Zipper a -> Zipper a shiftRight rl = case rl.before of [] -> case List.reverse rl.after of [] -> Zipper [] rl.focus [] x::xs -> Zipper xs x [rl.focus] x::xs -> Zipper xs x (rl.focus :: rl.after) {- From here we have private functions -} iterate1N : Int -> (a -> a) -> a -> List a iterate1N n f a = case n of 0 -> [] m -> f a :: List.map f (iterate1N (m - 1) f a)