2010-02-04 7 views
8

Ich brauche binäre combinators des TypsSind diese beiden Kombinatoren bereits in Haskell verfügbar?

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

oder vielleicht

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

(obwohl dies wäre nur die foldr1 der ersten, und ich brauche in der Regel nur zwei Booleschen Funktionen zu kombinieren.)

Sind diese eingebaut?


Wenn nicht, ist die Implementierung einfach:

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

oder vielleicht

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

Hoogle taucht nichts, aber manchmal seine Suche nicht richtig verallgemeinern. Irgendeine Idee, wenn diese eingebaut sind? Können sie aus Teilen einer bestehenden Bibliothek gebaut werden?

Wenn diese nicht integriert sind, könnten Sie neue Namen vorschlagen, weil diese Namen ziemlich schlecht sind. In der Tat, das ist der Hauptgrund, ich hoffe, dass sie eingebaut sind.

+0

'entweder :: (a -> c) -> (b -> c) -> Entweder ist ein b -> c 'bereits in' Prelude'; einen anderen Namen wählen? – ephemient

+0

Ich weiß, deshalb habe ich gehofft, dass jemand nette Alternativen vorschlagen könnte. –

Antwort

13

Control.Monad definiert eine 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 

Sie könnten mit Control.Applicative.liftA2 das gleiche tun.


nicht ernst es vorschlagen, aber ...

 
ghci> :t (. flip ($)) . flip all 
(. flip ($)) . flip all :: [a -> Bool] -> a -> Bool 
ghci> :t (. flip ($)) . flip any 
(. flip ($)) . flip any :: [a -> Bool] -> a -> Bool 
+0

Danke, ich wusste nichts über diese Instanz. Also habe ich 'liftM2 (&&)' nicht einmal versucht. –

+2

@ephemient: Wie wäre es mit 'fmap und. Sequenz "? – yairchu

+1

Ich denke ich würde mit Monoid ('Any' und' All', speziell) und 'mconcat' gehen. – jrockway

1

Ich kenne Builtins nicht, aber ich mag die Namen, die Sie vorschlagen.

getCoolNumbers = filter $ either even (< 42) 

Alternativ könnte man auch ein Operator-Symbol neben Typklassen für Alternativen vorstellen.

getCoolNumbers = filter $ even <|> (< 42) 
+1

Der Grund, warum ich 'weder' noch 'mag, ist wegen' Prelude.either' aka 'Data.Either.ither'. Abgesehen davon, dass ich sie bereits benutze, mag ich sie auch. :) –

+2

Über den Betreiber: <&&> ist unbenutzt und <||> nur von Parsec (nach hoogle). Das sind wahrscheinlich die besten Alternativen. –

6

Es ist kein builtin, aber die Alternative I bevorzugen Typklassen zu verallgemeinern die Boolesche Operationen zu Prädikaten von jedem verwenden 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) 

Ich liebe Haskell!

+1

Ooh, schön, obwohl die Fehlermeldungen, wenn Sie jemals versehentlich Aritäten mischen, * interessant * sein können. Ich würde mich tatsächlich darauf konzentrieren, diese '. && zu nennen. . || .' oder so ähnlich :-) – ephemient

+0

Das ist wirklich cool. Ich bin froh, dass ich darüber gestolpert bin! Haskell hört nie auf zu erstaunen: D –