Zhanyong Wan wrote:
Hello Simon,
Looking at the definition for deleteBy:
deleteBy :: (x -> a -> Bool) -> x -> [a] -> [a] deleteBy eq x [] = [] deleteBy eq x (y:ys) = if x `eq` y then ys else y : deleteBy eq x ys
I can't help wondering why it isn't
deleteBy' :: (a -> Bool) -> [a] -> [a] deleteBy' f [] = [] deleteBy' f (y:ys) = if f y then ys else y : deleteBy' f ys
The point is that in the definition of deleteBy, all references to eq and x are in the form (eq x), and hence the two parameters can be combined. Is there a reason that the current design was favored when Prelude was designed? Thanks.
- Zhanyong
Zhanyong, I didn't mean to open up a can of worms! Although, when viewed in isolation, it would make sense to change deleteBy as you suggest; but when we look at the conventions of the List module, I think that it would be undesirable, even if we didn't care about breaking programs, because it would break the "xBy" convention described below. Originally we had this: delete :: Eq a => a -> [a] -> [a] deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a] And all the functions "x" with a "xBy" form have types which are related in a particular way, for some functor f: x :: Eq a => f a xBy :: (a -> a -> Bool) -> f a Now, if we generalize the type of deleteBy as I previously suggested, we have these two types: delete :: Eq a => a -> [a] -> [a] deleteBy :: (a -> b -> Bool) -> a -> [b] -> [b] And it is still the case that functions "x" and "xBy" have types which are related as follows (generalizing the rule): x :: Eq a => f a a xBy :: (a -> b -> Bool) -> f a b (Where we would instantiate 'b' to 'a' for "xBy" functions which have a less general type.) - Mark