[Haskell-beginners] Using Maybe monad with Zipper

Hugo Ferreira hmf at inescporto.pt
Mon Nov 14 12:02:49 CET 2011


Hello,

I picked up code that originally had the following function:

leftCursor :: Z.Zipper a -> Maybe a
leftCursor z = if Z.beginp z then
                    Nothing
                else
                    Z.safeCursor $ Z.left z

However now I need a functions that returns all three elements
to the left of the zipper. I then considered using composition
and came up with the following:

left :: Maybe (Z.Zipper a) -> Maybe (Z.Zipper a)
left (Just z) = if Z.beginp z
               then
                 Nothing
               else
                 Just $ Z.left z
left Nothing = Nothing

cursor :: Maybe (Z.Zipper a) -> Maybe a
cursor (Just z) = Z.safeCursor z
cursor Nothing = Nothing

which I then used as follows:

instPrev1Of3TagRule :: POSTags -> Maybe TransformationRule
instPrev1Of3TagRule z = do
     (_, _, prev1)           <- leftCursor z
     (_, _, prev2)           <- (cursor . left . return) z
     (_, _, prev3)           <- (cursor . left . left . return) z
     (_, correct, incorrect) <- Z.safeCursor z
     return $ Prev1Of3TagRule (Replacement incorrect correct) prev1 
prev2 prev3

But I was not happy with this for two reasons:

1. I was repeating work needlessly. I should pick up the last
    zipper and just move the cursor again once for the next
    character.

2. I was not taking advantage of the Maybe Monad

So I finally changed the above to:

left :: Maybe (Z.Zipper a) -> Maybe (Z.Zipper a, a)
left (Just z) = if Z.beginp z
               then
                 Nothing
               else
                 Just $ (Z.left z, Z.cursor z)
left Nothing = Nothing

instPrev1Of3TagRule :: POSTags -> Maybe TransformationRule
instPrev1Of3TagRule z = do
     (z1,(_, _, prev1))      <- (left . return) z
     (z2, (_, _, prev2))     <- (left . return) z1
     (_z3, (_, _, prev3))    <- (left . return) z2
     (_, correct, incorrect) <- Z.safeCursor z
     return $ Prev1Of3TagRule (Replacement incorrect correct) prev1 
prev2 prev3

So my question is, is this correct? Can the above code be made
simpler/cleaner? Somehow the double use of Maybe seems wrong.

TIA,
Hugo F.







More information about the Beginners mailing list