I've been reading through John Hughes' Programming with Arrows, and I got to first exercise in which he asks the reader to implement a generic filter function for arrows, filterA. The spec says that it should behave like filter over (->) arrows and filterM over Kliesli arrows. I attempted to implement it as follows but what I ended up with seems somewhat simpler than the other examples I have seen of the solution online. I fear that I've missed something but my answer seems to work as the spec suggests. It matches filter for -> and filterM for Kliesli arrows. It also works in a reasonable way for stream functions.
listcase [] = Left ()
listcase (x:xs) = Right (x,xs)
filterA :: forall a arr. ArrowChoice arr => arr a Bool -> arr [a] [a]
filterA f = arr listcase >>>
arr (const []) ||| (switchA *** filterA f >>> arr (uncurry (++)))
where switchA :: ArrowChoice arr => arr a [a]
switchA = (f &&& id) >>> arr (\(b,x) -> if b then [x] else [])
Is this an acceptable implementation?
It seems acceptable to me. As an alternative you could consider using uncurry ($)
and
switchA :: ArrowChoice arr =>> arr a ([a] -> [a])
switchA = (f &&& arr id) >>> arr test
where
test (False, _) = id
test (True, x) = (x :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With