Вопрос

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

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

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

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

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

Они встроенные?


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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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)

Я люблю Хаскель!

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

getCoolNumbers = filter $ either even (< 42)

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

getCoolNumbers = filter $ even <|> (< 42)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top