Does it help the compiler to optimise, or is it just surplus work to add additional type signatures? For example, one often sees:
foo :: a -> b
foo x = bar x
where bar x = undefined
Rather than:
foo :: a -> b
foo x = bar x
where bar :: a -> b
bar x = undefined
If I omit the top level type signature, GHC gives me a warning, so if I don't get warnings I am quite confident my program is correct. But no warnings are issued if I omit the signature in a where clause.
Often definitions in
where
clauses are to avoid repeating yourself if a sub-expression occurs more than once in a definition. In such a case, the programmer thinks of the local definition as a simple stand-in for writing out the inline sub-expressions. You usually wouldn't explicitly type the inline sub-expressions, so you don't type thewhere
definition either. If you're doing it to save on typing, then the type declaration would kill all your savings.It seems quite common to introduce
where
to learners of Haskell with examples of that form, so they go on thinking that "normal style" is to not give type declarations for local definitions. At least, that was my experience learning Haskell. I've since found that many of my functions that are complicated enough to need awhere
block become rather inscrutable if I don't know the type of the local definitions, so I try to err towards always typing them now; even if I think the type is obvious while I'm writing the code, it may not be so obvious when I'm reading it after not having looked at it for a while. A little effort for my fingers is almost always outweighed by even one or two instances of having to run type inference in my head!Ingo's answer gives a good reason for deliberately not giving a type to a local definition, but I suspect the main reason is that many programmers have assimilated the rule of thumb that type declarations be provided for top level definitions but not for local definitions from the way they learned Haskell.