[Haskell-cafe] golf, predicate check function for MonadPlus (was Re: How to read safely?)

Dan Doel dan.doel at gmail.com
Mon Jul 6 21:49:46 EDT 2009


On Thursday 02 July 2009 6:36:09 am Jon Fairbairn wrote:
> check :: (MonadPlus m) => (a -> Bool) -> a -> m a
> check p a
>     | p a = return a
>     | otherwise = mzero
>
> I tried Hoogling for a function like check, but couldn't find it. Surely
> there's one in a library somewhere? It looks useful to me. (I'm rather
> taken by way the "check (all isSpace . snd)" part reads)
>
> Monad.guard comes close but fails to get the cigar; in fact
>
> guard b == check (const b) ()
>
> So check is more general.

I've often noticed the need for a similar function in conjunction with 
unfoldr:

  -- This is overly general for unfoldr, but it lines up with check
  stopAt :: (MonadPlus m) => (a -> Bool) -> (a -> b) -> a -> m b
  stopAt p f x
    | p x       = mzero
    | otherwise = return (f x)

  -- stopAt p f x = guard (not $ p x) >> return (f x)
  -- stopAt p f = liftM2 (>>) (guard . not . p) (return . f)
  -- etc.

Then you can write:

  unfoldr (stopAt p $ f)

where p is a stopping predicate based on the seed, and f unfolds the seed one 
step. This lets you use the many functions in the standard library that have 
types like:

  s -> (a, s)

where unfoldr wants them to instead be:

  s -> Maybe (a, s)

However, I don't really like the name stopAt, and have never come up with 
anything better.

And of course: check = flip stopAt id . not

-- Dan


More information about the Haskell-Cafe mailing list