You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
2.1 KiB
65 lines
2.1 KiB
module Lazy.Zipper exposing (..)
|
|
|
|
import Lazy exposing (Lazy)
|
|
import Lazy.List exposing (LazyList, (:::))
|
|
|
|
type alias Zipper a =
|
|
{ before : LazyList a
|
|
, focus : Lazy a
|
|
, after : LazyList a
|
|
}
|
|
|
|
|
|
{- Basic conversion -}
|
|
fromList : a -> List a -> Zipper a
|
|
fromList a l = Zipper Lazy.List.empty (pure a) (Lazy.List.fromList l)
|
|
|
|
toList : Zipper a -> List a
|
|
toList rl = Lazy.List.toList (Lazy.List.reverse rl.before) ++ [Lazy.force rl.focus] ++ Lazy.List.toList rl.after
|
|
|
|
{- Functor like things -}
|
|
map : (a -> b) -> Zipper a -> Zipper b
|
|
map f rl = Zipper (Lazy.List.map f rl.before) (Lazy.map f rl.focus) (Lazy.List.map f rl.after)
|
|
|
|
edit : (a -> a) -> Zipper a -> Zipper a
|
|
edit f rl = Zipper rl.before (Lazy.map f rl.focus) rl.after
|
|
|
|
{- Comonad functions -}
|
|
extract : Zipper a -> a
|
|
extract rl = rl.focus |> Lazy.force
|
|
|
|
duplicate : Zipper a -> Zipper (Zipper a)
|
|
duplicate rl = let
|
|
lefts = iterate1N (Lazy.List.length rl.before) shiftRight rl
|
|
rights = iterate1N (Lazy.List.length rl.after) shiftLeft rl
|
|
in Zipper lefts (pure 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 Lazy.List.headAndTail rl.after of
|
|
Just (x, xs) -> Zipper (Lazy.force rl.focus ::: rl.before) (pure x) xs
|
|
Nothing -> case Lazy.List.headAndTail (Lazy.List.reverse rl.before) of
|
|
Just (x, xs) -> Zipper (Lazy.List.singleton (Lazy.force rl.focus)) (pure x) xs
|
|
Nothing -> Zipper nil rl.focus nil
|
|
|
|
shiftRight : Zipper a -> Zipper a
|
|
shiftRight rl = case Lazy.List.headAndTail rl.before of
|
|
Just (x, xs) -> Zipper xs (pure x) (Lazy.force rl.focus ::: rl.after)
|
|
Nothing -> case Lazy.List.headAndTail (Lazy.List.reverse rl.after) of
|
|
Just (x, xs) -> Zipper xs (pure x) (Lazy.List.singleton (Lazy.force rl.focus))
|
|
Nothing -> Zipper nil rl.focus nil
|
|
|
|
{- From here we have private functions -}
|
|
iterate1N : Int -> (a -> a) -> a -> LazyList a
|
|
iterate1N n f a = case n of
|
|
0 -> nil
|
|
m -> f a ::: Lazy.List.map f (iterate1N (m - 1) f a)
|
|
|
|
nil = Lazy.List.empty
|
|
pure x = Lazy.lazy (always x)
|
|
|