Эти два комбинатора уже доступны в Haskell? - PullRequest
8 голосов
/ 04 февраля 2010

Мне нужны бинарные комбинаторы типа

(a -> Bool) -> (a -> Bool) -> a -> Bool

или, может быть,

[a -> Bool] -> a -> Bool

(хотя это будет просто foldr1 первого, и мне обычно нужно только объединить две логические функции.)

Это встроенные?


Если нет, реализация проста:

both f g x = f x && g x
either f g x = f x || g x

или, возможно,

allF fs x = foldr (\ f b -> b && f x) True fs
anyF fs x = foldr (\ f b -> b || f x) False fs

Google ничего не обнаруживает, но иногда его поиск не обобщается должным образом. Есть идеи, если они встроены? Могут ли они быть построены из частей существующей библиотеки?

Если они не встроены, вы можете предложить новые имена, потому что эти имена довольно плохие. На самом деле это главная причина, по которой я надеюсь, что они являются встроенными.

Ответы [ 3 ]

13 голосов
/ 04 февраля 2010

Control.Monad определяет instance Monad ((->) r), поэтому

ghci> :m Control.Monad
ghci> :t liftM2 (&&)
liftM2 (&&) :: (Monad m) => m Bool -> m Bool -> m Bool
ghci> liftM2 (&&) (5 <) (< 10) 8
True

Вы можете сделать то же самое с Control.Applicative.liftA2.


Не всерьез предлагать это, но ...

ghci> :t (. flip ($)) . flip all
(. flip ($)) . flip all :: [a -> Bool] -> a -> Bool
ghci> :t (. flip ($)) . flip any
(. flip ($)) . flip any :: [a -> Bool] -> a -> Bool
6 голосов
/ 05 февраля 2010

Это не встроенная функция, но я предпочитаю использовать классы типов для обобщения. логические операции для предикатов любой арности:

module Pred2 where

class Predicate a where
  complement :: a -> a
  disjoin    :: a -> a -> a
  conjoin    :: a -> a -> a

instance Predicate Bool where
  complement = not
  disjoin    = (||)
  conjoin    = (&&)

instance (Predicate b) => Predicate (a -> b) where
  complement = (complement .)
  disjoin f g x = f x `disjoin` g x
  conjoin f g x = f x `conjoin` g x


-- examples:

ge :: Ord a => a -> a -> Bool
ge = complement (<)

pos = (>0)
nonzero = pos `disjoin` (pos . negate)
zero    = complement pos `conjoin` complement (pos . negate)

Я люблю Haskell!

1 голос
/ 04 февраля 2010

Я не знаю встроенных функций, но мне нравятся имена, которые вы предлагаете.

getCoolNumbers = filter $ either even (< 42)

В качестве альтернативы можно подумать о символе оператора в дополнение к классам типов для альтернатив.

getCoolNumbers = filter $ even <|> (< 42)
...