Skip to content

Instantly share code, notes, and snippets.

@deniok
Created December 10, 2020 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deniok/af016087c5689e411137c170dbca4668 to your computer and use it in GitHub Desktop.
Save deniok/af016087c5689e411137c170dbca4668 to your computer and use it in GitHub Desktop.
FP_HSE2020Fall_15Zipper
module Fp15Zipper where
update2 :: new -> (a, (old, c)) -> (a, (new, c))
update2 v (x,(_,z)) = (x,(v,z))
{-
GHCi> stru = (1,(2,(3,4)))
GHCi> update2 42 stru
(1,(42,(3,4)))
GHCi> update2 "Hello" stru
(1,("Hello",(3,4)))
-}
type Triple a = (a,(a,a))
type TripleZ a = (a, -- фокус
Cntx a) -- контекст
data Cntx a = C1 ((),(a,a)) | C2 (a,((),a)) | C3 (a,(a,()))
type ListZ a = (a, -- фокус
CntxL a) -- контекст
type CntxL a = ([a],[a])
-- вкладываем список в зиппер
mklz :: [a] -> ListZ a
mklz (x:xs) = (x,([],xs))
-- навигация вперед
fwd :: ListZ a -> ListZ a
fwd (e,(xs,y:ys)) = (y,(e:xs,ys))
{-
GHCi> lz = mklz [0..3]
GHCi> lz
(0,([],[1,2,3]))
GHCi> fwd lz
(1,([0],[2,3]))
GHCi> (fwd . fwd) lz
(2,([1,0],[3]))
-}
-- навигация назад
bwd :: ListZ a -> ListZ a
bwd (e,(x:xs,ys)) = (x,(xs,e:ys))
-- распаковка зиппера в список
unlz :: ListZ a -> [a]
unlz (x,([],xs)) = x:xs
unlz z = unlz (bwd z)
{-
GHCi> lz' = (fwd . fwd) lz
GHCi> lz'
(2,([1,0],[3]))
GHCi> bwd lz'
(1,([0],[2,3]))
GHCi> unlz lz'
[0,1,2,3]
-}
-- внесение изменений в значение в фокусе
updLZ :: a -> ListZ a -> ListZ a
updLZ v (_,ctx) = (v,ctx)
insLZ :: a -> ListZ a -> ListZ a
insLZ v (e,(xs,ys)) = (v,(xs,e:ys))
delLZ :: ListZ a -> ListZ a
delLZ (_,(xs,y:ys)) = (y,(xs,ys))
delLZ (_,(x:xs,[])) = (x,(xs,[]))
{-
GHCi> (unlz . updLZ 42 . fwd . fwd . mklz) [0..3]
[0,1,42,3]
GHCi> (unlz . delLZ . bwd . updLZ 42 . fwd . fwd . mklz) [0..3]
[0,42,3]
GHCi> (unlz . insLZ 33 . insLZ 42 . fwd . fwd . mklz) [0..3]
[0,1,33,42,2,3]
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment