I have a problem with the following function
sum f l1 l2 = (f l1) + (f l2)
It doesn't work with
sum length [1,2] ['a','b']. When I try this I get
No instance for (Num Char) arising from the literal ‘1’
error so the problem is with types. When I try
:t function, I get
sum :: Num a => (t -> a) -> t -> t -> a. So, if I understand this correctly, I can't just use
+ function with both numerical and character values at the same time but I lack the deeper understanding of why exactly is this the case and how to fix it.
I tried a couple of things, like using
let for one of the literals or
id function, but this doesn't seem to work. Any help?
When inferring types from your code, GHC will assume that you intend
f to have a relatively simple type, and intend
l2 to have the same type, so that both are suitable as input to
You apparently want to pass a polymorphic
f, that can work on both
[Char]. Depending how general you want to get, here are some options:
Works on lists,
f must work on any list regardless of element type:
sum0 :: (forall x. [x] -> Int) -> [a] -> [b] -> Int sum0 f l1 l2 = f l1 + f l2
Works on lists & other
Foldable types (Vector, Set, Matrix), as long as both inputs are the same
Foldable. The first argument can be
length, or something specific to the choice of
sum1 :: (Num n, Foldable f) => (forall x. f x -> n) -> f a -> f b -> n sum1 f l1 l2 = f l1 + f l2
l2 to be different
f must work for any foldable.
length still qualifies, but
Set.size isn't general enough.
sum2 :: (Num n, Foldable s, Foldable t) => (forall f x. Foldable f => f x -> n) -> s a -> t b -> n sum2 f l1 l2 = f l1 + f l2
In practice, with a function this small, I think it's easier just to write
length l1 + length l2 at each use site than to define a function with any of the complex types above. But it's nice to know we can write these types when we want to.