以下模式在Haskell代码中经常出现。有没有更短的写作方式?
if pred x
then Just x
else Nothing
答案 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]]
用于表示谓词的结果。
对于像这样的专业版,你真的没有太多可以缩短它。它已经很简单了。简洁之间有一个很好的界限,只是为你的代码打高尔夫球来计算字符数,对于这个简单的事情,我不会真的担心试图“改进”它......