
Ben Franksen
Achim Schneider wrote:
ChrisK
wrote: zeroNothing Nothing = Nothing zeroNothing (Just n) = if n == 0 then Nothing else (Just n)
versus
zeroNothing Nothing = Nothing zeroNothing x@(Just n) = if n == 0 then Nothing else x
versus
zeroNothing Nothing = Nothing zeroNothing x = let (Just n) = x in if n == 0 then Nothing else x
so, @ is kind of like a let, just with its arguments flipped.
However, if x@(Just n) fails to match, the next clause is chosen, whereas the variable pattern x matches always. Thus, the last version works only because the other possible case (Nothing) has already been handled. IOW, in the second version of zeroNothing you may swap the order of patterns, but not in the third one.
Actually, I considered working it out to nothingIf :: (a -> Bool) -> Maybe a -> Maybe a nothingIf f m = m >>= (\j -> if f j then Nothing else Just j) nothingIf' :: (a -> Bool) -> Maybe a -> Maybe a nothingIf' f m = m >>= (\j -> if f j then Nothing else m) zeroNothing = nothingIf (== 0) zeroNothing' = nothingIf' (== 0) , but was too lazy. Hopefully only because it completely messes up my point. OTOH, zeroIf :: MonadPlus m => (a -> Bool) -> m a -> m a zeroIf f m = m >>= (\nz -> if f nz then mzero else m) zeroZero :: (MonadPlus m, Num a) => m a -> m a zeroZero = zeroIf (==0) makes it interesting again as you can't construct a Just value with it.