Using Haskell addition function with both Num and Char values

  • A+

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 l1 and l2 to have the same type, so that both are suitable as input to f.

You apparently want to pass a polymorphic f, that can work on both [Int] and [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 Foldable, like Set.size.

sum1 :: (Num n, Foldable f) => (forall x. f x -> n) -> f a -> f b -> n sum1 f l1 l2 = f l1 + f l2 

Allow l1 and l2 to be different Foldable types. 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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: