Skip to content

Instantly share code, notes, and snippets.

@dtchepak
Created November 7, 2012 12:16
Show Gist options
  • Select an option

  • Save dtchepak/4031132 to your computer and use it in GitHub Desktop.

Select an option

Save dtchepak/4031132 to your computer and use it in GitHub Desktop.
learning list zippers the hard way
import Control.Arrow ((>>>))
import Data.List.Zipper
import Data.Maybe
{- ref:
- http://www.reddit.com/r/dailyprogrammer/comments/12qi5b/1162012_challenge_111_easy_star_delete/
- -}
starDelete' :: String -> String
starDelete' [] = []
starDelete' "*" = []
starDelete' (_:'*':xs) = starDelete' ('*':xs)
starDelete' ('*':_:xs) = starDelete' xs
starDelete' (x:xs) = x : starDelete' xs
starDelete :: String -> String
starDelete = catMaybes . toList . toEnd starDeleteZ . fromList . fmap Just
toEnd :: (Zipper a -> Zipper a) -> Zipper a -> Zipper a
toEnd f z
| endp z = z
| otherwise = toEnd f . right . f $ z
starDeleteZ :: Zipper (Maybe Char) -> Zipper (Maybe Char)
starDeleteZ = toEnd (\z -> if cursor z == Just '*' then blat z else z)
where blat = blatLeft >>> blatRightWhile (== Just '*') >>> replace Nothing
blatLeft :: Zipper (Maybe Char) -> Zipper (Maybe Char)
blatLeft z = if beginp z then z
else left >>> replace Nothing >>> right $ z
blatRightWhile :: (Maybe a -> Bool) -> Zipper (Maybe a) -> Zipper (Maybe a)
blatRightWhile pred z
| endp z = z
| pred . cursor $ z = replace Nothing >>> right >>> blatRightWhile pred $ z
| otherwise = z
examples =
[ ("adf*lp", "adp")
, ("a*o", "")
, ("*dech*", "ec")
, ("de**po", "do")
, ("sa*n*ti", "si")
, ("abc", "abc")
]
main =
let p (input, exp) = input ++ " --> " ++ check exp (starDelete' input)
check exp actual =
if exp == actual then actual
else "was " ++ actual ++ ", expected " ++ exp
in mapM_ (putStrLn . p) examples
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment