8

我需要这种类型的二进制组合器

(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

Hoogle 什么也没找到,但有时它的搜索并不能正确概括。知道这些是否是内置的吗?它们可以从现有库的片段中构建吗?

如果这些不是内置的,您可能会建议新名称,因为这些名称非常糟糕。事实上,这是我希望它们是内置的主要原因。

4

3 回答 3

13

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
真的

你可以对Control.Applicative.liftA2.


不是认真建议,但是...

ghci> :t (.flip ($)) 。全部翻转
(。翻转($))。翻转所有 :: [a -> Bool] -> a -> Bool
ghci> :t (.flip ($)) 。翻转任何
(。翻转($))。翻转任何 :: [a -> Bool] -> a -> Bool
于 2010-02-04T18:26:09.410 回答
6

它不是内置的,但我更喜欢的替代方法是使用类型类将布尔运算推广到任何数量的谓词:

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)

我爱哈斯克尔!

于 2010-02-05T02:01:57.630 回答
1

我不知道内置,但我喜欢你提出的名字。

getCoolNumbers = filter $ either even (< 42)

或者,除了类型类之外,还可以考虑一个运算符符号作为替代方案。

getCoolNumbers = filter $ even <|> (< 42)
于 2010-02-04T18:25:58.550 回答