16

以下模式在 Haskell 代码中经常出现。有没有更短的写法?

if pred x
then Just x
else Nothing
4

6 回答 6

28

mfilter您正在Control.Monad寻找:

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

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

请注意,如果条件不依赖于 的内容MonadPlus,您可以改为:

"foo" <$ guard (odd 3) -- Just "foo"
"foo" <$ guard (odd 4) -- Nothing
于 2011-09-17T09:54:49.723 回答
7

嗯...您正在寻找一个组合器,它接受一个a, 一个函数a -> Bool并返回一个Maybe a. 停止!胡歌时间。没有完全匹配,但find非常接近:

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

我怀疑您是否真的可以在某个地方找到您的功能。但是为什么不自己定义呢?

ifMaybe :: (a -> Bool) -> a -> Maybe a
ifMaybe f a | f a = Just a
ifMaybe _ _       = Nothing
于 2011-09-17T09:29:52.970 回答
5

利用:

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

来自 Data.Bool.HT。

于 2011-09-17T10:32:49.717 回答
5

您可以使用guard来实现此行为:

guard (pred x) >> return x

这是一种非常有用的行为,我什ensure至在我自己的一次性代码中定义了这种行为(每个人都有这样的事情,对吧?;-):

ensure p x = guard (p x) >> return x
于 2011-09-17T14:26:38.440 回答
1

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...

于 2011-09-17T19:23:03.443 回答
1
f pred x = if pred x then Just x else Nothing

鉴于上述定义,您可以简单地编写:

f pred x

当然,这与 Daniel Wagnerensure或 FUZxxl 的ifMaybe. 但它的名字很简单f,使它最短,它的定义正是你给出的代码,使它最容易证明是正确的。;)

一些ghci,只是为了好玩

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

如果你不能说,这不是一个非常严肃的答案。其他人更有洞察力,但我无法抗拒“让这段代码更短”的诙谐回应。

于 2011-09-17T18:40:35.950 回答