What is a good reason to use a type signature for functions when the compiler can infer the types

后端 未结 4 596
梦谈多话
梦谈多话 2021-01-17 09:44

I am trying to code using \'good Haskell style\' and so am trying to follow typical coding standards I find around. Also, compiling with -Wall and -Werror as I am used to w

相关标签:
4条回答
  • 2021-01-17 10:06

    There are several reasons.

    1. It may make the code easier for humans to read. (OTOH, if you have dozens of tiny definitions, sometimes the type signatures add more clutter.)
    2. If your implementation is wrong, the compiler may infer the wrong type. This may cause other functions' types to be inferred wrong, finally resulting in a type error very far away from the actual broken function.
    3. You may want to give a function a less polymorphic type than it could have, for performance reasons.
    4. You may want to use type aliases. This allows you to quickly change a type in several places, and also to document some of the intent behind a value. (Compare FilePath vs String.)
    5. The compiler can figure out types automatically, but not all external tools can do this. (E.g., originally Haddock would refuse to produce documentation for functions lacking an explicit type signature - although I gather this is fixed now.)

    It is worth noting that some people advocate that you start with the type signatures, and fill in the implementations later.

    At any rate, most people seem to recommend type signatures for all or most top-level declarations. Whether you give them for local variables / functions is a matter of taste.

    0 讨论(0)
  • 2021-01-17 10:07

    Your contrived example is really contrived, since the function body does not depend on the type of contents of the list. In this case it is indeed difficult to see what's the benefit of defining the type to be [String] -> ([String],[String]) instead of [a]->([a],[a])

    If you attempt to define a function that depends on the contents, you will see that the type definition is not the only thing you need to change. For example, changing a list for MArray is going to be far more involved, not just using a function that happens to have the same name in a different module. So qualifying the name during refactoring in a few narrow cases is not a good enough reason to not specify type signatures.

    Specifying the type tells the compiler a little bit of the intent. Then the compiler will be able to report the mismatch of the intent and the implementation.

    0 讨论(0)
  • 2021-01-17 10:08

    If you make a mistake in defining your function, the compiler might infer a type that isn't what you expected it to be. If you've declared the type you expect, the compiler will report the error in the function's definition.

    Without the declaration, the compiler has no way to know that its inferred type is "wrong", and it will instead end up reporting errors in the places where you try to call the function, which makes it less clear where the problem really lies.

    If the calling functions don't have type declarations either, then instead of reporting errors there, the compiler might just infer incorrect types for those too, causing problems in their callers. You'll end up getting an error message somewhere, but it may be quite far removed from the actual root of the problem.


    Also, you can declare a more specific type than what the compiler would infer. For example, if you write the function:

    foo n = n + 1
    

    The compiler will infer the type Num a => a -> a, which means it must compile generic code that can work with any Num instance. If you declare the type as Int -> Int, the compiler may be able to produce more efficient code that's specialized for integers only.


    Finally, type declarations serve as documentation. The compiler may be able to infer the types of complex expressions, but it's not so easy for a human reader. A type declaration provides the "big picture" that can help a programmer understand what the function does.

    Note that Haddock comments are attached to declarations, not definitions. Writing a type declaration is the first step toward providing additional documentation for a function using Haddock.

    0 讨论(0)
  • 2021-01-17 10:19

    I would consider documentation one advantage of having an explicit type signature.

    From "Types and Programming Languages":

    Types are also useful when reading programs. The type declarations in procedure headers and module interfaces constitute a form of documentation, giving useful hints about behavior. Moreover, unlike descriptions embedded in comments, this form of documentation cannot become outdated, since it is checked during every run of the compiler. This role of types is particularly important in module signatures.

    0 讨论(0)
提交回复
热议问题