ZipperをConcurrent Cleanで実装してみた。

とりあえず、リストについて。
悩んだのは(というか、いつも悩むのは)、例外処理をどうしようかということ。nextとprevはタプルで真偽値を返して、それ以外はabortにしたけれど、どうするのが使いやすいのだろう?

::ListZipper a = ListZipper [a] [a]

lzToListZipper :: [a] -> ListZipper a
lzToListZipper lst = ListZipper [] lst

lzToList :: (ListZipper a) -> [a]
lzToList (ListZipper xs ys) = xs ++ ys

lzIsBegin :: (ListZipper a) -> Bool
lzIsBegin (ListZipper [] _) = True
lzIsBegin _ = False

lzIsEnd :: (ListZipper a) -> Bool
lzIsEnd (ListZipper _ []) = True
lzIsEnd _ = False

lzNext :: (ListZipper a) -> (Bool, ListZipper a)
lzNext (ListZipper xs [y:ys]) = (True, ListZipper [y:xs] ys)
lzNext z = (False, z)

lzPrev :: (ListZipper a) -> (Bool, ListZipper a)
lzPrev (ListZipper [x:xs] ys) = (True, ListZipper xs [x:ys])
lzPrev z = (False, z)

lzGet :: (ListZipper a) -> a
lzGet (ListZipper _ [y:_]) = y
lzGet _ = abort "ListZipper: not found"

lzSet :: a (ListZipper a) -> ListZipper a
lzSet e (ListZipper xs [y:ys]) = ListZipper xs [e:ys]
lzSet _ _ = abort "ListZipper: not found"

lzInsert :: a (ListZipper a) -> ListZipper a
lzInsert e (ListZipper xs ys) = ListZipper xs [e:ys]

lzRemove :: (ListZipper a) -> ListZipper a
lzRemove (ListZipper xs [_:ys]) = ListZipper xs ys
lzRemove _ = abort "ListZipper: not found"