I started learning Haskell following the recommandations in this answer. So I am just implementing easy list functions, and I stumble onto a difference in the compiler behavior I cannot explain to myself :
-- Impl 1
elementAt :: (Integral b) => [a] -> b -> a
elementAt xs id = xs !! (fromIntegral(id-1))
-- Impl 2
elementAt' :: (Num b) => [a] -> b -> a
elementAt' xs id = xs !! (id-1)
With following signatures :
fromIntegral :: (Integral a, Num b) => a -> b
(!!) :: [a] -> Int -> a
I get an error only for the second implementation, elementAt'
.
Could not deduce (b ~ Int)
from the context (Num b)
If I understand correctly, it means that the operator (!!) is expecting an Int instance as its second argument (as seen from the signature), but we only guarantee that the provided parameter is conforming to the Num typeclass (inferred from elemenAt'
signature), which is wider than Int.
With that in mind, I do not understand why the first implementation actually works, knowing that fromIntegral
also returns an value that is only conforming to the Num typeclass.