Skip to content

Instantly share code, notes, and snippets.

@mbrcknl
Created May 14, 2015 02:28
Show Gist options
  • Save mbrcknl/c647ff697c1cd84bf832 to your computer and use it in GitHub Desktop.
Save mbrcknl/c647ff697c1cd84bf832 to your computer and use it in GitHub Desktop.
Just some ideas from briefly mucking about with zippers with nkpart and newmana
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
import qualified Data.Map as M
import Control.Applicative as A
newtype JObject = JObject (M.Map String Json)
newtype JList = JList [Json]
data Json
= JLs JList
| JObj JObject
| JPrim String
| JNull
data ListContext = ListContext JList JList JContext
data ObjectContext = ObjectContext String JObject JContext
data JContext
= Top
| ListCtx JList JList JContext
| ObjectCtx String JObject JContext
data JZipper focus context = JZipper focus context
class Focus t where
focus :: JZipper Json context -> Maybe (JZipper t context)
blur :: JZipper t context -> JZipper Json context
instance Focus JObject where
focus (JZipper (JObj object) context) = Just (JZipper object context)
focus _ = Nothing
blur (JZipper object context) = JZipper (JObj object) context
class Up t c where
up :: JZipper (Maybe Json) c -> JZipper t JContext
instance Up JList ListContext where
up (JZipper focus (ListContext (JList left) (JList right) context))
= JZipper (JList (reverse left ++ maybe id (:) focus right)) context
instance Up JObject ObjectContext where
up (JZipper focus (ObjectContext field (JObject object) context))
= JZipper (JObject (M.update (const focus) field object)) context
class Down i t c where
down :: i -> JZipper t JContext -> Maybe (JZipper Json c)
instance Down String JObject ObjectContext where
down field (JZipper (JObject object) context) = refocus <$> M.lookup field object
where
refocus on = JZipper on (ObjectContext field (JObject (M.delete field object)) context)
-- TODO: get rid of the partial functions!
instance Down Int JList ListContext where
down index (JZipper (JList list) context)
| index < length list = Just $ JZipper (list !! index) (ListContext left right context)
| otherwise = Nothing
where
left = JList $ reverse $ take index list
right = JList $ drop (index+1) list
relabel :: (String -> String) -> JZipper focus ObjectContext -> JZipper focus ObjectContext
relabel f (JZipper focus (ObjectContext field others context))
= JZipper focus (ObjectContext (f field) others context)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment