2010-02-04 6 views
8

necesito combinadores binarios del tipo¿Estos dos combinadores ya están disponibles en Haskell?

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

o tal vez

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

(aunque esto no sería más que la foldr1 de la primera, y por lo general sólo es necesario combinar dos funciones booleanas.)

¿Están incorporados?


Si no es así, la implementación es simple:

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

o tal vez

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

Hoogle vuelve a nada, pero a veces su búsqueda no generalizar correctamente. Alguna idea si estos están incorporados? ¿Se pueden construir a partir de piezas de una biblioteca existente?

Si no están incorporados, puede sugerir nuevos nombres, porque estos nombres son bastante malos. De hecho, esa es la razón principal por la que espero que sean incorporados.

+0

'cualquiera :: (a -> c) -> (b -> c) -> O bien b -> c' ya está en' Preludio'; elegir un nombre diferente? – ephemient

+0

Lo sé, es por eso que esperaba que alguien pudiera sugerir buenas alternativas. –

Respuesta

13

Control.Monad define un instance Monad ((->) r), por lo

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

que podría hacer lo mismo con Control.Applicative.liftA2.


no quiere decir en serio, pero ...

 
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

Gracias, no sabía sobre esa instancia. Así que ni siquiera intenté con 'liftM2 (&&)'. –

+2

@ephemient: ¿qué tal 'fmap y. secuencia'? – yairchu

+1

Creo que iría con Monoid ('Any' y' All', específicamente) y 'mconcat'. – jrockway

1

No sé builtins, pero me gustan los nombres que usted propone.

getCoolNumbers = filter $ either even (< 42) 

Alternativamente, se podría pensar en un símbolo de operador además de tipos de clases para las alternativas.

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

La razón por la que no me gusta 'cualquiera' se debe a' Prelude.either' aka 'Data.Either.either'. Además de ser utilizado, me gustan también. :) –

+2

Sobre el operador: <&&> está sin usar y <||> solo por Parsec (de acuerdo con hoogle). Entonces esas son probablemente las mejores alternativas. –

6

No es una orden interna, pero la alternativa prefiero es el uso de las clases de tipos de generalizar las operaciones booleanas a los predicados de cualquier 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!

+1

Ooh, lindo, aunque los mensajes de error si alguna vez mezclas accidentalmente aries pueden ser * interesantes *. Me inclinaría por llamar a estos '. &&. . || .' o algo así :-) – ephemient

+0

Esto es realmente genial. Me alegro de haber tropezado con esto! Haskell nunca deja de sorprender: D –

Cuestiones relacionadas