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"