-
Notifications
You must be signed in to change notification settings - Fork 0
/
LoopZipper.hs
53 lines (37 loc) · 1.11 KB
/
LoopZipper.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{-# LANGUAGE BangPatterns #-}
module LoopZipper where
import Control.Comonad
import Data.Default
import qualified Data.Foldable as Foldable
import Data.Monoid
import Data.Sequence
import Prelude hiding (length, take)
import qualified Prelude
data Loop s = Loop !s !(Seq s)
loopRead (Loop s _) = s
loopWrite s (Loop _ r) = Loop s r
loopLength (Loop _ r) = 1 + length r
loopLeft (Loop s r) =
let (!init) :> (!last) = viewr r in
Loop last (s <| init)
loopRight (Loop s r) =
let (!head) :< (!tail) = viewl r in
Loop head (tail |> s)
toList :: Loop a -> [a]
toList (Loop s r) =
s : (Foldable.toList r)
seqTail :: Seq a -> Seq a
seqTail !s =
case viewl s of
EmptyL -> s
_ :< t -> t
instance (Default a) => Monoid (Loop a) where
mempty = Loop def $ fromList [def]
mappend (Loop ls l) (Loop rs r) = Loop ls (l >< (rs <| r))
instance (Default a) => Default (Loop a) where
def = mempty
instance Functor Loop where
fmap f (Loop s r) = Loop (f s) (fmap f r)
instance Comonad Loop where
extract = loopRead
duplicate !lz = Loop lz (seqTail . iterateN ((+ 1) . pred . loopLength $ lz) loopRight $ lz)