Compiled with ghc --make
, these two programs produce the exact same binaries:
-- id1a.hs
main = print (id' 'a')
id' :: a -> a
id' x = x
-- id1b.hs
main = print (id' 'a')
id' :: Char -> Char
id' x = x
Is this just because of how trivial/contrived my example is, or does this hold true as programs get more complex?
Also, is there any good reason to avoid making my types as general as possible? I usually try keep specifics out where I don't need them, but I am not extremely familiar with the effects of this on compiled languages, especially Haskell/GHC.
Side Note:
I seem to recall a recent SO question where the answer was to make a type more specific in order to improve some performance issue, though I cannot find it now, so I may have imagined it.
Edit:
I understand from a usability / composability standpoint that more general is always better, I'm more interested in the effects this has on the compiled code. Is it possible for me to be too eager in abstracting my code? Or is this usually not a problem in Haskell?
I would go and make everything as general as possible. If you run into performance issues you can start thinking about messing with concrete implementations but IMHO this will not be a problem very often and if this really gets an problem then maybe your performance need will be as great as to think about moving into imperative-land again ;)
Is there any good reason to avoid making my types as general as possible?
No, as long as you have the Specialize pragma at your disposal for those rare situations where it might actually matter.
Is this just because of how trivial/contrived my example is
Yes. Namely, try splitting the definition of id'
and main
into different modules and you should see a difference.
However, Carsten is right: there may be performance-related reasons to use concrete types, but you should generally start with general types and use concrete implementations only if you actually have a problem.
General types usually make your functions more usable, in my opinion.
This may be a poor example, but if you're writing a function such as elem (takes a list and an element and returns true if the list contains that element and false otherwise), using specific types will constrain the usability of your function. ie. if you specify the type as Int, you can't use that function to check if a String contains a certain character, for example.
I'm not quite sure about performance, but I haven't experienced any issues and I use general types almost all the time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With