2 ms·
They are definitely some downsides to the first definition. For instance, the error messages will often be much harder to read. For the second one you might get
by TheCoelacanth 9y ago
They are definitely some downsides to the first definition. For instance, the error messages will often be much harder to read. For the second one you might get something straight forward like it expected `[Int]` but the actual type was `Int`. For the first one you will probably get something about not being able to deduce some long constraint for some long type. That might be possible to improve with better tooling, but for now it is a very real downside.
I think that especially for application code (as opposed to library code), it is a mistake to make your type signature far more generic than you need right away, especially because it is usually easy to switch to the more generic type declaration later without changing much existing code.
- tome 9y agoThis is a good point. I think there's some merit in doing traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) mySpecialTraverse :: Int -> IO Float -> [Int] -> IO [Float] mySpecialTraverse = traverse in some instances.