编写此代码的方法较短

时间:2011-09-17 09:17:20

标签: haskell if-statement combinators maybe

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

if pred x
then Just x
else Nothing

6 个答案:

答案 0 :(得分:28)

您正在寻找mfilter in 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

答案 1 :(得分:7)

嗯...您正在寻找一个组合a,一个函数a -> Bool并返回Maybe a的组合子。停止! Hoogle time。没有完全匹配,但find非常接近:

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

我怀疑你能在某个地方找到你的功能。但为什么不自己定义呢?

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

答案 2 :(得分:5)

使用:

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

来自Data.Bool.HT。

答案 3 :(得分:5)

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

guard (pred x) >> return x

这是一个非常有用的行为,我甚至在我自己的一小段代码中定义ensure一次性(每个人都有这样的东西,对吧?; - ):

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

答案 4 :(得分:1)

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

鉴于上述定义,您只需写下:

f pred x

当然,这与Daniel Wagner的ensure或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

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

答案 5 :(得分:1)

通常我非常喜欢非常通用的代码,但实际上我发现这个功能非常有用,专门用于Maybe,我保留它而不是使用guard,{{ 1}}等等。

我使用的名称是mfilter,我通常会用它来做这样的事情:

justIf

基本上,需要在复合表达式中进行某种元素过滤或检查的东西,因此∀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]] 用于表示谓词的结果。

对于像这样的专业版,你真的没有太多可以缩短它。它已经很简单了。简洁之间有一个很好的界限,只是为你的代码打高尔夫球来计算字符数,对于这个简单的事情,我不会真的担心试图“改进”它......