Shorter way to write this code

流过昼夜 提交于 2019-12-09 02:20:17

问题


The following pattern appears very frequently in Haskell code. Is there a shorter way to write it?

if pred x
then Just x
else Nothing

回答1:


You're looking for mfilter in Control.Monad:

mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a

-- mfilter odd (Just 1) == Just 1
-- mfilter odd (Just 2) == Nothing

Note that if the condition doesn't depend on the content of the MonadPlus, you can write instead:

"foo" <$ guard (odd 3) -- Just "foo"
"foo" <$ guard (odd 4) -- Nothing



回答2:


Hm... You are looking for a combinator that takes an a, a function a -> Bool and returns a Maybe a. Stop! Hoogle time. There is no complete match, but find is quite close:

find :: (a -> Bool) -> [a] -> Maybe a

I doubt that you can actually find your function somewhere. But why not define it by yourself?

ifMaybe :: (a -> Bool) -> a -> Maybe a
ifMaybe f a | f a = Just a
ifMaybe _ _       = Nothing



回答3:


You can use guard to achieve this behavior:

guard (pred x) >> return x

This is such a generally useful behavior that I've even defined ensure in my own little suite of code for one-offs (everybody has such a thing, right? ;-):

ensure p x = guard (p x) >> return x



回答4:


Use:

(?:) (5>2) (Just 5,Nothing)

from Data.Bool.HT.




回答5:


f pred x = if pred x then Just x else Nothing

Given the above definition, you can simply write:

f pred x

Of course this is no different than Daniel Wagner's ensure or FUZxxl's ifMaybe. But it's name is simply f, making it the shortest, and it's definition is precisely the code you gave, making it the most easily proven correct. ;)

Some ghci, just for fun

ghci> let f pred x = if pred x then Just x else Nothing
ghci> f (5>) 2
Just 2
ghci> f (5>) 6
Nothing

If you couldn't tell, this isn't a very serious answer. The others are a bit more insightful, but I couldn't resist the tongue-in-cheek response to "make this code shorter".




回答6:


Usually I'm a big fan of very generic code, but I actually find this exact function useful often enough, specialized to Maybe, that I keep it around instead of using guard, mfilter, and the like.

The name I use for it is justIf, and I'd typically use it for doing things like this:

∀x. x ⊢ import Data.List
∀x. x ⊢ unfoldr (justIf (not . null . snd) . splitAt 3) [1..11]
[[1,2,3],[4,5,6],[7,8,9]]

Basically, stuff where some sort of element-wise filtering or checking needs to be done in a compound expression, so Maybe is used to indicate the result of the predicate.

For the specialized version like this, there really isn't much you can do to make it shorter. It's already pretty simple. There's a fine line between being concise, and just golfing your code for character count, and for something this simple I wouldn't really worry about trying to "improve" it...



来源:https://stackoverflow.com/questions/7453744/shorter-way-to-write-this-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!