Skip to content

Instantly share code, notes, and snippets.

@artisonian
Last active October 13, 2017 12:48
Show Gist options
  • Save artisonian/102b278ef1f6ed9fe851c448689dc2e9 to your computer and use it in GitHub Desktop.
Save artisonian/102b278ef1f6ed9fe851c448689dc2e9 to your computer and use it in GitHub Desktop.
A simple list zipper data structure for maintaining a selection in a list of values
module ZipList exposing
( ZipList
, init, singleton
, toList, toSelectionList
, get, forward, back
, select
)
type ZipList a =
ZipList
{ prev : List a
, current : a
, next : List a
}
toList : ZipList a -> List a
toList (ZipList { prev, current, next }) =
(List.reverse prev) ++ [current] ++ next
toSelectionList : ZipList a -> List (Bool, a)
toSelectionList (ZipList { prev, current, next }) =
let
notSelected x =
( False, x )
in
(List.reverse <| List.map notSelected prev)
++ [ ( True, current ) ]
++ List.map notSelected next
singleton : a -> ZipList a
singleton x =
init [] x
init : List a -> a -> ZipList a
init tail head =
ZipList { prev = [], current = head, next = tail }
get : ZipList a -> a
get (ZipList { current }) =
current
forward : ZipList a -> ZipList a
forward (ZipList { prev, current, next } as zipList) =
case next of
[] ->
zipList
x :: xs ->
ZipList
{ prev = (current :: prev)
, current = x
, next = xs
}
back : ZipList a -> ZipList a
back (ZipList { prev, current, next } as zipList) =
case prev of
[] ->
zipList
x :: xs ->
ZipList
{ prev = xs
, current = x
, next = (current :: next)
}
select : a -> ZipList a -> ZipList a
select item (ZipList { prev, current, next } as zipList) =
if List.member item prev then
select item (back zipList)
else if List.member item next then
select item (forward zipList)
else
zipList
@thedumbtechguy
Copy link

any usage examples?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment