2009-11-10 13 views
6

napisać "Mapa f (mapa g xs)" jako jednego połączenia do mapy można napisaćHaskell, filtry łańcuchowym

przykładowe xs = map (FG) xs

Ale jak piszesz "filter p (filter q xs)" jako pojedyncze połączenie do filtrowania? operator kropki nie działa na filtr, tak jak robi to w przypadku map. zgadujesz, że używałbyś czegoś innego dla predykatów?

Odpowiedz

9

Jeśli zdefiniowano funkcję both który wyglądał tak:

both :: (a -> Bool) -> (a -> Bool) -> a -> Bool 
both f g x = f x && g x 

Następnie można napisać:

example xs = filter (both p q) xs 

Nie jestem pewien, czy jest to standardowa funkcja, że ​​robi to dla ciebie. ..

+0

dzięki człowiek, który działa pewnie eno ugh. wciąż myślę, że może być bardziej bezpośredni sposób robienia tego chociaż (?) – derp

1

Chciałbym zdefiniować funkcję pomocnika - może to być napisane bardziej deklaratywnie, ale nie mam zainstalowanego GHCI w tym systemie do testowania:

allPredicates :: [a -> Bool] -> a -> Bool 
allPredicates []  _ = True 
allPredicates (p:ps) x = p x && allPredicates ps x 

następnie

filter (allPredicates [p, q]) xs 
+0

'allPredicates = (. flip ($)). przerzuć wszystkie ' – ephemient

+1

Lub nieco mniej zaciemnione' allPredicates x y = all (flip ($) y) x'. Jak efektywnie GHC rozplątuje skomplikowane zastosowania 'flipa '?Wydaje mi się, że potrzebowałem wcześniej usunąć użytek 'flip' dla celów wydajnościowych. Oh, "AllPredicates" Johna może działać dość słabo, ponieważ funkcje rekursywne nie mogą być wstawiane. Och, dziwne, nie ma "gdzie pójść ..." w definicji "wszystkiego" w Data.List, której jestem prawie pewien, że potrzebujesz do wstawiania. –

+0

Ahh nie, "statyczna transformacja argumentów" czyni ją nierekurencyjną: http://stackoverflow.com/a/9660027/667457 –

6

Dlaczego nie lista ze zrozumieniem?

example = [x | x <- xs, p x, q x] 
-- for example 
example = [x | x <- [1..10], (>3) x, x<5 ] -- [4] 
+0

Tak, rozumienie list działa dobrze tutaj. Pytanie faktycznie wywodzi się z tutorialu, który miałem w tym tygodniu, a sugestia, że ​​tam był, była prostym sposobem na zrobienie tego. Zrozumienie listy jest najszybsze, jakie znalazłem do tej pory i zaczynam myśleć, że nie może być porównywalna jak w przypadku mapy i "funkcji składowych". dziękuję wszystkim! – derp

+0

Zawsze można utworzyć regułę przepisywania. Konwertuj filtr f. filtr g do \ a -> filtr (f a && g a). Oczywiście jest to tylko substytut dla bardziej eleganckiego rozumienia list, chociaż może być szybszy (przeczenie). – codebliss

4

Wywołanie listę funkcji na czymś, co jest w istocie funkcja w Control.Monad ap robi. Wtedy po prostu and wyniki. Jedyna lekka brzydota polega na tym, że ap wymaga, aby oba argumenty były w tej samej monadie (List w tym przypadku), więc musimy skomponować go z return, aby pracować tutaj.

import Control.Monad 
filterByMany funcs = filter (and . ap funcs . return) 
4

Chciałbym zdefiniować wyrażenie lambda.

module Main where 

overTen :: Int -> Bool 
overTen = (>10) 

main :: IO() 
main = do 
    print $ filter (\x -> overTen x && even x) [1..20] 

wyjściowa:

$ ghci Test.hs 
GHCi, version 6.10.4: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer ... linking ... done. 
Loading package base ... linking ... done. 
[1 of 1] Compiling Main    (Test.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> main 
[12,14,16,18,20] 
*Main> 
+0

To właśnie robi "GHC-O2" automatycznie (no prawie: jest kilka różnych faz reguł przepisywania, a często fazy pośrednie łączą się z innymi materiałami przed/zamiast z powrotem w filtrze) –

8
 
$ ghci 
Prelude> :m +Control.Arrow 
Prelude Control.Arrow> :t uncurry (&&) . ((0 <) &&& (< 10)) 
uncurry (&&) . ((0 <) &&& (< 10)) :: (Num a, Ord a) => a -> Bool 
Prelude Control.Arrow> filter (uncurry (&&) . ((0 <) &&& (< 10))) [0..15] 
[1,2,3,4,5,6,7,8,9] 

Albo zadeklarować własne operatorów, jeśli będziesz robił to częściej.

infixr 3 &&: 
p &&: q = \a -> p a && q a 
infixr 2 ||: 
p ||: q = \a -> p a || q a 
not' = (.) not 
all' = foldr (&&:) $ const True 
any' = foldr (||:) $ const False 

example xs = filter (p &&: q ||: not' r) xs 
3
import Data.Foldable 
import Data.Monoid 

p = (>4) 
g = (<10) 

main = print $ filter (getAll . foldMap (All.) [p,g]) [1..10] 

wyjścia

[5,6,7,8,9] 

tylko dlatego, że listy są składane i można połączyć predykatywne wyniki z All monoid

2

Co o czymś takim:

example xs = filter (forAll [p,q,r,s,t,u,v]) xs 

forAll:: [(a -> Bool)] -> a -> Bool 
forAll funcs x = all (map ($ x) funcs) 
+0

masz na myśli, 'forAll fs x = i [fx | f <- fs] '. :) Z 'all' jest' forAll fs x = all ($ x) fs' (bez 'mapy'). :) –