Sono queste due combinatori già disponibili in Haskell?
-
18-09-2019 - |
Domanda
Ho bisogno combinatori binari del tipo
(a -> Bool) -> (a -> Bool) -> a -> Bool
o forse
[a -> Bool] -> a -> Bool
(anche se questo potrebbe essere solo la foldr1 del primo, e di solito solo bisogno di combinare due funzioni booleane.)
Sono questi built-in?
In caso contrario, l'applicazione è semplice:
both f g x = f x && g x
either f g x = f x || g x
o forse
allF fs x = foldr (\ f b -> b && f x) True fs
anyF fs x = foldr (\ f b -> b || f x) False fs
Hoogle salta fuori nulla, ma a volte la sua ricerca non generalizzare correttamente. Qualsiasi idea se questi sono built-in? Possono essere costruite da pezzi di una libreria esistente?
Se questi non sono built-in, si potrebbe suggerire nuovi nomi, perché questi nomi sono piuttosto male. In realtà questo è il motivo principale Spero che sono built-in.
Soluzione
Control.Monad
definisce un instance Monad ((->) r)
, così
ghci> :m Control.Monad ghci> :t liftM2 (&&) liftM2 (&&) :: (Monad m) => m Bool -> m Bool -> m Bool ghci> liftM2 (&&) (5 <) (< 10) 8 True
Si potrebbe fare lo stesso con Control.Applicative.liftA2
.
Non per suggerire sul serio, ma ...
ghci> :t (. flip ($)) . flip all (. flip ($)) . flip all :: [a -> Bool] -> a -> Bool ghci> :t (. flip ($)) . flip any (. flip ($)) . flip any :: [a -> Bool] -> a -> Bool
Altri suggerimenti
Non è un incorporato, ma l'alternativa preferisco è quello di utilizzare le classi di tipo generalizzare le operazioni booleane per predicati di qualsiasi arità:
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)
Amo Haskell!
Non so comandi incorporati, ma mi piacciono i nomi che proponi.
getCoolNumbers = filter $ either even (< 42)
In alternativa, si potrebbe pensare ad un simbolo dell'operatore oltre a typeclasses di alternative.
getCoolNumbers = filter $ even <|> (< 42)