Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are these two combinators already available in Haskell?

I need binary combinators of the type

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

or maybe

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

(though this would just be the foldr1 of the first, and I usually only need to combine two boolean functions.)

Are these built-in?


If not, the implementation is simple:

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

or perhaps

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

Hoogle turns up nothing, but sometimes its search doesn't generalise properly. Any idea if these are built-in? Can they be built from pieces of an existing library?

If these aren't built-in, you might suggest new names, because these names are pretty bad. In fact that's the main reason I hope that they are built-in.

like image 408
Nathan Shively-Sanders Avatar asked Feb 04 '10 18:02

Nathan Shively-Sanders


2 Answers

Control.Monad defines an instance Monad ((->) r), so

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

You could do the same with Control.Applicative.liftA2.


Not to seriously suggest it, but...

ghci> :t (. flip ($)) . flip all
(. flip ($)) . flip all :: [a -> Bool] -> a -> Bool
ghci> :t (. flip ($)) . flip any
(. flip ($)) . flip any :: [a -> Bool] -> a -> Bool
like image 188
ephemient Avatar answered Nov 11 '22 15:11

ephemient


It's not a builtin, but the alternative I prefer is to use type classes to generalize the Boolean operations to predicates of any arity:

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)

I love Haskell!

like image 24
Norman Ramsey Avatar answered Nov 11 '22 15:11

Norman Ramsey