module Text.XML.HaXml.Combinators
(
CFilter
, keep, none, children, childrenBy, position
, elm, txt, tag, attr, attrval, tagWith
, find, iffind, ifTxt
, o, union, cat, andThen
, (|>|), with, without
, (/>), (</), et
, path
, deep, deepest, multi
, when, guards, chip, inplace, recursivelyInPlace, foldXml
, mkElem, mkElemAttr, literal, cdata, replaceTag, replaceAttrs, addAttribute
, ThenElse(..), (?>)
, LabelFilter
, oo, x
, numbered, interspersed, tagged, attributed, textlabelled, extracted
) where
import Text.XML.HaXml.Types
import Text.XML.HaXml.Namespaces
import Data.Maybe (fromMaybe)
infixl 6 `with`, `without`
infixr 5 `o`, `oo`, `union`, `andThen`
infixl 5 />, </, |>|
infixr 4 `when`, `guards`
infixr 3 ?>, :>
type CFilter i = Content i -> [Content i]
keep :: a->[a]
keep :: forall a. a -> [a]
keep a
x = [a
x]
none :: a->[b]
none :: forall a b. a -> [b]
none a
_ = []
children :: CFilter i
children :: forall i. CFilter i
children (CElem (Elem QName
_ [Attribute]
_ [Content i]
cs) i
_) = [Content i]
cs
children Content i
_ = []
position :: Int -> CFilter i -> CFilter i
position :: forall i. Int -> CFilter i -> CFilter i
position Int
n CFilter i
f = (\[Content i]
cs-> [[Content i]
csforall a. [a] -> Int -> a
!!Int
n]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f
elm, txt :: CFilter i
tag :: String -> CFilter i
attr :: String -> CFilter i
attrval :: Attribute -> CFilter i
tagWith :: (String->Bool) -> CFilter i
elm :: forall i. CFilter i
elm x :: Content i
x@(CElem Element i
_ i
_) = [Content i
x]
elm Content i
_ = []
txt :: forall i. CFilter i
txt x :: Content i
x@(CString Bool
_ CharData
_ i
_) = [Content i
x]
txt x :: Content i
x@(CRef Reference
_ i
_) = [Content i
x]
txt Content i
_ = []
tag :: forall i. CharData -> CFilter i
tag CharData
t x :: Content i
x@(CElem (Elem QName
n [Attribute]
_ [Content i]
_) i
_) | CharData
tforall a. Eq a => a -> a -> Bool
==QName -> CharData
printableName QName
n = [Content i
x]
tag CharData
_ Content i
_ = []
tagWith :: forall i. (CharData -> Bool) -> CFilter i
tagWith CharData -> Bool
p x :: Content i
x@(CElem (Elem QName
n [Attribute]
_ [Content i]
_) i
_) | CharData -> Bool
p (QName -> CharData
printableName QName
n) = [Content i
x]
tagWith CharData -> Bool
_ Content i
_ = []
attr :: forall i. CharData -> CFilter i
attr CharData
n x :: Content i
x@(CElem (Elem QName
_ [Attribute]
as [Content i]
_) i
_) | CharData
n forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` forall a b. (a -> b) -> [a] -> [b]
map (QName -> CharData
printableNameforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall a b. (a, b) -> a
fst) [Attribute]
as = [Content i
x]
attr CharData
_ Content i
_ = []
attrval :: forall i. Attribute -> CFilter i
attrval Attribute
av x :: Content i
x@(CElem (Elem QName
_ [Attribute]
as [Content i]
_) i
_) | Attribute
av forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Attribute]
as = [Content i
x]
attrval Attribute
_ Content i
_ = []
find :: String -> (String->CFilter i) -> CFilter i
find :: forall i. CharData -> (CharData -> CFilter i) -> CFilter i
find CharData
key CharData -> CFilter i
cont c :: Content i
c@(CElem (Elem QName
_ [Attribute]
as [Content i]
_) i
_) = CharData -> CFilter i
cont (forall a. Show a => a -> CharData
show (forall {a} {c}. Eq a => a -> [(a, c)] -> c
lookfor (CharData -> QName
N CharData
key) [Attribute]
as)) Content i
c
where lookfor :: a -> [(a, c)] -> c
lookfor a
x = forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => CharData -> a
error (CharData
"missing attribute: "forall a. [a] -> [a] -> [a]
++CharData
key)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup a
x
iffind :: String -> (String->CFilter i) -> CFilter i -> CFilter i
iffind :: forall i.
CharData -> (CharData -> CFilter i) -> CFilter i -> CFilter i
iffind CharData
key CharData -> CFilter i
yes CFilter i
no c :: Content i
c@(CElem (Elem QName
_ [Attribute]
as [Content i]
_) i
_) =
case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (CharData -> QName
N CharData
key) [Attribute]
as of
Maybe AttValue
Nothing -> CFilter i
no Content i
c
(Just v :: AttValue
v@(AttValue [Either CharData Reference]
_)) -> CharData -> CFilter i
yes (forall a. Show a => a -> CharData
show AttValue
v) Content i
c
iffind CharData
_key CharData -> CFilter i
_yes CFilter i
no Content i
other = CFilter i
no Content i
other
ifTxt :: (String->CFilter i) -> CFilter i -> CFilter i
ifTxt :: forall i. (CharData -> CFilter i) -> CFilter i -> CFilter i
ifTxt CharData -> CFilter i
yes CFilter i
_no c :: Content i
c@(CString Bool
_ CharData
s i
_) = CharData -> CFilter i
yes CharData
s Content i
c
ifTxt CharData -> CFilter i
_yes CFilter i
no Content i
c = CFilter i
no Content i
c
data ThenElse a = a :> a
(?>) :: (a->[b]) -> ThenElse (a->[b]) -> (a->[b])
a -> [b]
p ?> :: forall a b. (a -> [b]) -> ThenElse (a -> [b]) -> a -> [b]
?> (a -> [b]
f :> a -> [b]
g) = \a
c-> if (Bool -> Bool
notforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (t :: * -> *) a. Foldable t => t a -> Bool
nullforall b c a. (b -> c) -> (a -> b) -> a -> c
.a -> [b]
p) a
c then a -> [b]
f a
c else a -> [b]
g a
c
o :: CFilter i -> CFilter i -> CFilter i
CFilter i
f o :: forall i. CFilter i -> CFilter i -> CFilter i
`o` CFilter i
g = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CFilter i
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
g
union :: (a->[b]) -> (a->[b]) -> (a->[b])
union :: forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
union = forall a b d c. (a -> b -> d) -> (c -> a) -> (c -> b) -> c -> d
lift forall a. [a] -> [a] -> [a]
(++)
where
lift :: (a->b->d) -> (c->a) -> (c->b) -> c -> d
lift :: forall a b d c. (a -> b -> d) -> (c -> a) -> (c -> b) -> c -> d
lift a -> b -> d
f c -> a
g c -> b
h c
x = a -> b -> d
f (c -> a
g c
x) (c -> b
h c
x)
cat :: [a->[b]] -> (a->[b])
cat :: forall a b. [a -> [b]] -> a -> [b]
cat [] = forall a b. a -> b -> a
const []
cat [a -> [b]]
fs = forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
union [a -> [b]]
fs
andThen :: (a->c) -> (c->a->b) -> (a->b)
andThen :: forall a c b. (a -> c) -> (c -> a -> b) -> a -> b
andThen a -> c
f c -> a -> b
g a
x = c -> a -> b
g (a -> c
f a
x) a
x
childrenBy :: CFilter i -> CFilter i
childrenBy :: forall i. CFilter i -> CFilter i
childrenBy CFilter i
f = CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children
(|>|) :: (a->[b]) -> (a->[b]) -> (a->[b])
a -> [b]
f |>| :: forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
|>| a -> [b]
g = \a
x-> let fx :: [b]
fx = a -> [b]
f a
x in if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [b]
fx then a -> [b]
g a
x else [b]
fx
with :: CFilter i -> CFilter i -> CFilter i
CFilter i
f with :: forall i. CFilter i -> CFilter i -> CFilter i
`with` CFilter i
g = forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
notforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (t :: * -> *) a. Foldable t => t a -> Bool
nullforall b c a. (b -> c) -> (a -> b) -> a -> c
.CFilter i
g) forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f
without :: CFilter i -> CFilter i -> CFilter i
CFilter i
f without :: forall i. CFilter i -> CFilter i -> CFilter i
`without` CFilter i
g = forall a. (a -> Bool) -> [a] -> [a]
filter (forall (t :: * -> *) a. Foldable t => t a -> Bool
nullforall b c a. (b -> c) -> (a -> b) -> a -> c
.CFilter i
g) forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f
(/>) :: CFilter i -> CFilter i -> CFilter i
CFilter i
f /> :: forall i. CFilter i -> CFilter i -> CFilter i
/> CFilter i
g = CFilter i
g forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children forall i. CFilter i -> CFilter i -> CFilter i
`o` CFilter i
f
(</) :: CFilter i -> CFilter i -> CFilter i
CFilter i
f </ :: forall i. CFilter i -> CFilter i -> CFilter i
</ CFilter i
g = CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`with` (CFilter i
g forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children)
et :: (String->CFilter i) -> CFilter i -> CFilter i
et :: forall i. (CharData -> CFilter i) -> CFilter i -> CFilter i
et CharData -> CFilter i
f CFilter i
g = (CharData -> CFilter i
f forall a i. (a -> CFilter i) -> LabelFilter i a -> CFilter i
`oo` forall i. CFilter i -> LabelFilter i CharData
tagged forall i. CFilter i
elm)
forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
|>|
(CFilter i
g forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
txt)
path :: [CFilter i] -> CFilter i
path :: forall i. [CFilter i] -> CFilter i
path [CFilter i]
fs = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall i. CFilter i -> CFilter i -> CFilter i
o) forall a. a -> [a]
keep [CFilter i]
fs
deep, deepest, multi :: CFilter i -> CFilter i
deep :: forall i. CFilter i -> CFilter i
deep CFilter i
f = CFilter i
f forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
|>| (forall i. CFilter i -> CFilter i
deep CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children)
deepest :: forall i. CFilter i -> CFilter i
deepest CFilter i
f = (forall i. CFilter i -> CFilter i
deepest CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children) forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
|>| CFilter i
f
multi :: forall i. CFilter i -> CFilter i
multi CFilter i
f = CFilter i
f forall a b. (a -> [b]) -> (a -> [b]) -> a -> [b]
`union` (forall i. CFilter i -> CFilter i
multi CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i
children)
when :: CFilter i -> CFilter i -> CFilter i
guards :: CFilter i -> CFilter i -> CFilter i
CFilter i
f when :: forall i. CFilter i -> CFilter i -> CFilter i
`when` CFilter i
g = CFilter i
g forall a b. (a -> [b]) -> ThenElse (a -> [b]) -> a -> [b]
?> CFilter i
f forall a. a -> a -> ThenElse a
:> forall a. a -> [a]
keep
CFilter i
g guards :: forall i. CFilter i -> CFilter i -> CFilter i
`guards` CFilter i
f = CFilter i
g forall a b. (a -> [b]) -> ThenElse (a -> [b]) -> a -> [b]
?> CFilter i
f forall a. a -> a -> ThenElse a
:> forall a b. a -> [b]
none
chip :: CFilter i -> CFilter i
chip :: forall i. CFilter i -> CFilter i
chip CFilter i
f (CElem (Elem QName
n [Attribute]
as [Content i]
cs) i
i) = [ forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem QName
n [Attribute]
as (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CFilter i
f [Content i]
cs)) i
i ]
chip CFilter i
_f Content i
c = [Content i
c]
inplace :: CFilter i -> CFilter i
inplace :: forall i. CFilter i -> CFilter i
inplace CFilter i
f c :: Content i
c@(CElem (Elem QName
name [Attribute]
as [Content i]
_) i
i) = [ forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem QName
name [Attribute]
as (CFilter i
f Content i
c)) i
i ]
inplace CFilter i
_f Content i
c = [Content i
c]
recursivelyInPlace :: CFilter i -> CFilter i
recursivelyInPlace :: forall i. CFilter i -> CFilter i
recursivelyInPlace CFilter i
f = forall i. CFilter i -> CFilter i
inplace (forall i. CFilter i -> CFilter i
recursivelyInPlace CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` CFilter i
f)
foldXml :: CFilter i -> CFilter i
foldXml :: forall i. CFilter i -> CFilter i
foldXml CFilter i
f = CFilter i
f forall i. CFilter i -> CFilter i -> CFilter i
`o` forall i. CFilter i -> CFilter i
chip (forall i. CFilter i -> CFilter i
foldXml CFilter i
f)
mkElem :: String -> [CFilter i] -> CFilter i
mkElem :: forall i. CharData -> [CFilter i] -> CFilter i
mkElem CharData
h [CFilter i]
cfs Content i
t = [ forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem (CharData -> QName
N CharData
h) [] (forall a b. [a -> [b]] -> a -> [b]
cat [CFilter i]
cfs Content i
t)) forall a. HasCallStack => a
undefined ]
mkElemAttr :: String -> [(String,CFilter i)] -> [CFilter i] -> CFilter i
mkElemAttr :: forall i.
CharData -> [(CharData, CFilter i)] -> [CFilter i] -> CFilter i
mkElemAttr CharData
h [(CharData, CFilter i)]
as [CFilter i]
cfs = \Content i
t-> [ forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem (CharData -> QName
N CharData
h) (forall a b. (a -> b) -> [a] -> [b]
map (forall {i}. Content i -> (CharData, CFilter i) -> Attribute
attr Content i
t) [(CharData, CFilter i)]
as) (forall a b. [a -> [b]] -> a -> [b]
cat [CFilter i]
cfs Content i
t))
forall a. HasCallStack => a
undefined ]
where attr :: Content i -> (CharData, CFilter i) -> Attribute
attr Content i
t (CharData
n,CFilter i
vf) =
let v :: CharData
v = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ CharData
s | (CString Bool
_ CharData
s i
_) <- (forall i. CFilter i -> CFilter i
deep forall i. CFilter i
txt forall i. CFilter i -> CFilter i -> CFilter i
`o` CFilter i
vf) Content i
t ]
in (CharData -> QName
N CharData
n, [Either CharData Reference] -> AttValue
AttValue [forall a b. a -> Either a b
Left CharData
v])
literal :: String -> CFilter i
literal :: forall i. CharData -> CFilter i
literal CharData
s = forall a b. a -> b -> a
const [forall i. Bool -> CharData -> i -> Content i
CString Bool
False CharData
s forall a. HasCallStack => a
undefined]
cdata :: String -> CFilter i
cdata :: forall i. CharData -> CFilter i
cdata CharData
s = forall a b. a -> b -> a
const [forall i. Bool -> CharData -> i -> Content i
CString Bool
True CharData
s forall a. HasCallStack => a
undefined]
replaceTag :: String -> CFilter i
replaceTag :: forall i. CharData -> CFilter i
replaceTag CharData
n (CElem (Elem QName
_ [Attribute]
as [Content i]
cs) i
i) = [forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem (CharData -> QName
N CharData
n) [Attribute]
as [Content i]
cs) i
i]
replaceTag CharData
_ Content i
_ = []
replaceAttrs :: [(String,String)] -> CFilter i
replaceAttrs :: forall i. [(CharData, CharData)] -> CFilter i
replaceAttrs [(CharData, CharData)]
as (CElem (Elem QName
n [Attribute]
_ [Content i]
cs) i
i) = [forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem QName
n [Attribute]
as' [Content i]
cs) i
i]
where as' :: [Attribute]
as' = forall a b. (a -> b) -> [a] -> [b]
map (\(CharData
n,CharData
v)-> (CharData -> QName
N CharData
n, [Either CharData Reference] -> AttValue
AttValue [forall a b. a -> Either a b
Left CharData
v])) [(CharData, CharData)]
as
replaceAttrs [(CharData, CharData)]
_ Content i
_ = []
addAttribute :: String -> String -> CFilter a
addAttribute :: forall a. CharData -> CharData -> CFilter a
addAttribute CharData
name CharData
val (CElem (Elem QName
n [Attribute]
as [Content a]
cs) a
i) =
[forall i. Element i -> i -> Content i
CElem (forall i. QName -> [Attribute] -> [Content i] -> Element i
Elem QName
n (Attribute
aforall a. a -> [a] -> [a]
:[Attribute]
as) [Content a]
cs) a
i]
where a :: Attribute
a = (CharData -> QName
N CharData
name, [Either CharData Reference] -> AttValue
AttValue [forall a b. a -> Either a b
Left CharData
val])
addAttribute CharData
_ CharData
_ Content a
_ = []
type LabelFilter i a = Content i -> [(a,Content i)]
oo :: (a->CFilter i) -> LabelFilter i a -> CFilter i
a -> CFilter i
f oo :: forall a i. (a -> CFilter i) -> LabelFilter i a -> CFilter i
`oo` LabelFilter i a
g = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry a -> CFilter i
f) forall b c a. (b -> c) -> (a -> b) -> a -> c
. LabelFilter i a
g
x :: (CFilter i->LabelFilter i a) -> (CFilter i->LabelFilter i b) ->
(CFilter i->LabelFilter i (a,b))
CFilter i -> LabelFilter i a
f x :: forall i a b.
(CFilter i -> LabelFilter i a)
-> (CFilter i -> LabelFilter i b)
-> CFilter i
-> LabelFilter i (a, b)
`x` CFilter i -> LabelFilter i b
g = \CFilter i
cf Content i
c-> let gs :: [b]
gs = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (CFilter i -> LabelFilter i b
g CFilter i
cf Content i
c)
fs :: [a]
fs = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst (CFilter i -> LabelFilter i a
f CFilter i
cf Content i
c)
in forall a b. [a] -> [b] -> [(a, b)]
zip (forall a b. [a] -> [b] -> [(a, b)]
zip [a]
fs [b]
gs) (CFilter i
cf Content i
c)
numbered :: CFilter i -> LabelFilter i Int
numbered :: forall i. CFilter i -> LabelFilter i Int
numbered CFilter i
f = forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f
interspersed :: String -> CFilter i -> String -> LabelFilter i String
interspersed :: forall i.
CharData -> CFilter i -> CharData -> LabelFilter i CharData
interspersed CharData
a CFilter i
f CharData
b =
(\[Content i]
xs-> forall a b. [a] -> [b] -> [(a, b)]
zip (forall a. Int -> a -> [a]
replicate (forall {a}. [a] -> Int
len [Content i]
xs) CharData
a forall a. [a] -> [a] -> [a]
++ [CharData
b]) [Content i]
xs) forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f
where
len :: [a] -> Int
len [] = Int
0
len [a]
xs = forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs forall a. Num a => a -> a -> a
- Int
1
tagged :: CFilter i -> LabelFilter i String
tagged :: forall i. CFilter i -> LabelFilter i CharData
tagged CFilter i
f = forall i a. (Content i -> a) -> CFilter i -> LabelFilter i a
extracted forall {i}. Content i -> CharData
name CFilter i
f
where name :: Content i -> CharData
name (CElem (Elem QName
n [Attribute]
_ [Content i]
_) i
_) = QName -> CharData
printableName QName
n
name Content i
_ = CharData
""
attributed :: String -> CFilter i -> LabelFilter i String
attributed :: forall i. CharData -> CFilter i -> LabelFilter i CharData
attributed CharData
key CFilter i
f = forall i a. (Content i -> a) -> CFilter i -> LabelFilter i a
extracted forall {i}. Content i -> CharData
att CFilter i
f
where att :: Content i -> CharData
att (CElem (Elem QName
_ [Attribute]
as [Content i]
_) i
_) =
case forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (CharData -> QName
N CharData
key) [Attribute]
as of
Maybe AttValue
Nothing -> CharData
""
(Just v :: AttValue
v@(AttValue [Either CharData Reference]
_)) -> forall a. Show a => a -> CharData
show AttValue
v
att Content i
_ = CharData
""
textlabelled :: CFilter i -> LabelFilter i (Maybe String)
textlabelled :: forall i. CFilter i -> LabelFilter i (Maybe CharData)
textlabelled CFilter i
f = forall i a. (Content i -> a) -> CFilter i -> LabelFilter i a
extracted forall {i}. Content i -> Maybe CharData
text CFilter i
f
where text :: Content i -> Maybe CharData
text (CString Bool
_ CharData
s i
_) = forall a. a -> Maybe a
Just CharData
s
text Content i
_ = forall a. Maybe a
Nothing
extracted :: (Content i->a) -> CFilter i -> LabelFilter i a
Content i -> a
proj CFilter i
f = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Content i
c->[(Content i -> a
proj Content i
c, Content i
c)]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. CFilter i
f