Во-первых, найдите себе пробел для понимания и назовите свои подвыражения:
elim b w ps = filter (\p -> all (\x -> x `elem` p) b &&
all (\x -> x `notElem` p) w
) ps
= filter foo ps
where
foo p = all (\x -> x `elem` p) b &&
all (\x -> x `notElem` p) w
= filter foo ps
where
foo p = all tst1 b && all tst2 w
where
tst1 = (\x -> x `elem` p)
tst2 = (\x -> x `notElem` p)
= filter foo ps
where
foo p = (&&) (all tst1 b) (all tst2 w)
where
tst1 x = elem x p
tst2 y = notElem y p
Теперь, что это делает? Или еще лучше, что это? Давайте рассмотрим некоторые типы, чтобы создать наше понимание здесь:
filter :: (a -> Bool) -> [a] -> [a]
foo :: a -> Bool
ps :: [a]
filter foo ps :: [a]
p :: a
foo p :: Bool
(&&) :: Bool -> Bool -> Bool
all tst1 b :: Bool
all tst2 w :: Bool
---------------------------
all :: (t -> Bool) -> [t] -> Bool
tst1 :: t -> Bool
tst2 :: t -> Bool
b :: [t]
w :: [t]
---------------------------
......
---------------------------
elim b w ps :: [a]
elim :: [t] -> [t] -> [a] -> [a]
Завершите картину, работая с типами tst1
и tst2
, чтобы выяснить взаимосвязь между типами t
и a
.
tst1 :: t -> Bool -- tst1 x = elem x p
tst2 :: t -> Bool -- tst2 y = notElem y p
x :: t
y :: t
elem :: Eq t => t -> [t] -> Bool
notElem :: Eq t => t -> [t] -> Bool
p :: [t] -- it was : a !
Таким образом a ~ [t]
и [a] ~ [[t]]
и, наконец,
elim b w ps :: [[t]]
elim :: Eq t => [t] -> [t] -> [[t]] -> [[t]]
Итак, filter foo
оставляет только те p
s в ps
, для которых foo p == True
.
А это значит all tst1 b == True
и all tst2 w == True
.
И это означает, что каждый x
в b
является элементом p
, а каждый y
в w
является , а не элементом в p
. Или, другими словами, только такие p
s в ps
оставлены одни в результирующем списке, для которого
foo p = (b \\ p) == [] && (p \\ w) == p
имеет место:
import Data.List (\\)
elim b w ps = [ p | p <- ps, (b \\ p) == [], (p \\ w) == p ]