Более короткий способ написать этот код - PullRequest
16 голосов
/ 17 сентября 2011

Следующий шаблон очень часто встречается в коде на Haskell.Есть ли более короткий способ написать это?

if pred x
then Just x
else Nothing

Ответы [ 6 ]

28 голосов
/ 17 сентября 2011

Вы ищете 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
7 голосов
/ 17 сентября 2011

Хм ... Вы ищете комбинатор, который принимает a, функцию a -> Bool и возвращает Maybe a.Стоп! Время в Google .Полного совпадения нет, но find довольно близко:

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

Я сомневаюсь, что вы где-то действительно можете найти свою функцию.Но почему бы не определить это самостоятельно?

ifMaybe :: (a -> Bool) -> a -> Maybe a
ifMaybe f a | f a = Just a
ifMaybe _ _       = Nothing
5 голосов
/ 17 сентября 2011

Вы можете использовать guard для достижения этого поведения:

guard (pred x) >> return x

Это в целом такое полезное поведение, которое я даже определил ensure в своем собственном небольшом наборе кода для разовых (у каждого есть такая вещь, верно?; -):

ensure p x = guard (p x) >> return x
5 голосов
/ 17 сентября 2011

Использование:

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

из Data.Bool.HT.

1 голос
/ 17 сентября 2011

Обычно я большой поклонник очень общего кода, но на самом деле я нахожу эту точную функцию достаточно полезной, специализированной для Maybe, поэтому я использую ее вместо использования guard, 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]]

По сути, вещи, в которых требуется некоторая поэлементная фильтрация или проверка в составном выражении, поэтому для указания результата предиката используется Maybe.

Для такой специализированной версии вы действительно мало что можете сделать, чтобы сделать ее короче. Это уже довольно просто. Существует тонкая грань между лаконичностью и просто игрой в ваш код для подсчета символов, и для чего-то такого простого, я бы не стал беспокоиться о том, чтобы попытаться «улучшить» его ...

1 голос
/ 17 сентября 2011
f pred x = if pred x then Just x else Nothing

Учитывая приведенное выше определение, вы можете просто написать:

f pred x

Конечно, это ничем не отличается от ensure Даниэля Вагнера или ifMaybe FUZxxl. Но его имя просто 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

Если вы не могли сказать, это не очень серьезный ответ. Другие немного более проницательны, но я не мог удержаться от насмешливого ответа «сделать этот код короче».

...