7

GHC warns that I don't have the function signatures at the top level. I don't get why I would need them. The problem with providing them is that they are quite sophisticated, like this one (autogenerated):

applyValue :: forall t t1 t2 t3 t4.
                (t2 -> t)
                -> (t2 -> t3 -> t4 -> t1) -> t2 -> t3 -> t4 -> (t -> Bool) -> [t1]

So why would I bother adding them?

the function itself:

applyValue getValueAt stitchAndMove at fabric mark matchAt =
   if matchAt (getValueAt at)
   then [stitchAndMove at fabric mark]
   else []
3
  • Do you have any extensions enabled? Commented Oct 28, 2013 at 3:36
  • Can we see some code? Commented Oct 28, 2013 at 3:37
  • 6
    If this happens because you're compiling with -Wall, you can use -fno-warn-missing-signatures. It's considered good practice not to leave them out - see Daniel Wagner's answer for reasons why. Commented Oct 28, 2013 at 3:38

1 Answer 1

25
  • As a form of machine-checkable documentation. If you believe that type to be the right type, putting it there asks the compiler to double-check that you didn't hose your own interface during your later inevitable refactoring sessions.
  • As human-readable documentation. Although as you observe, when you notice you're writing an awful machine-generated type, it's probably time to think about what (type-level) abstractions you need to make it human-readable.
  • For haddock. Haddock comments get attached to type signatures, not bindings, so if you leave out a type signature, your carefully hand-written documentation will be silently ignored.
  • To improve error messages and ghci query results: although the actual names of type variables don't matter, GHC tries hard to preserve names when they're provided by the user. Something like (node -> Bool) -> (edge -> Bool) -> (graph -> Bool) can be much more readable than (t1 -> Bool) -> (t2 -> Bool) -> (t3 -> Bool), even though they're equivalent.
Sign up to request clarification or add additional context in comments.

3 Comments

Your point makes sense, I have another quick question though, is there a way to reuse signature blocks, say I have a signature of a function f1 that is long and sophisticated, now f2 takes f1, so it's everything about f2 + whatever f1 was. I wonder if I can save some work by assigning the signature f1 to some of name (type?) and refer to it by that name when I am defining the signature of f2. Thanks
@AlekseyBykov Yes, this is what type aliases do. You can read about them in the Report or your favorite tutorial.
Signatures are sometimes necessary even if you don't care about documentation or error messages. Sometimes it is ambiguous what instance of a type class you want, and thus you need to explicitly constrain it in order for it to compile.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.