5 ms·
I don't think you are really arguing against static type checking in that post, but rather the explicit type declarations that often accompany it. These are no
by ggchappell 13y ago
I don't think you are really arguing against static type checking in that post, but rather the explicit type declarations that often accompany it.
These are not the same thing. See Haskell for a counterexample.
EDIT: I see that Haskell is mentioned in the comments. Still, I don't see any understanding there that static vs. dynamic is not the issue.
- Buttons840 13y agoHaskell is inspiring, I did the interactive "Try Haskell" tutorial and though "Oh, it's dynamically typed." Later I found it it's just really good and inferring types. From what I've read, it sounds like good Haskell practice is explicitly declare types on functions, but otherwise never declare types. The compiler can then use the few explicit declarations you have made to infer all the other types.
- IsTom 13y agoMost of the time compiler can do without most top-level declarations too. They're a form of documentation enforced by the compiler.
- asdasf 13y agoThe compiler can already infer all the types anyways, you don't need to declare types. It is considered good practice (and -Wall warns for it) to provide types for top level definitions, as they are usually important enough to warrant this form of machine checked documentation. note: Yes I know the compiler can't actually infer all types all the time, but the exceptions are obvious and require type information in dynamically typed languages too (ie. convert a string to an int: you have to tell it you want an int, you can't just say "convert this string" and have it guess what you want it converted to).
- ent 13y agoBut the cool thing is that in many (most?) cases you can actually infer the type of reading from a string. You are going to do something with that value right? So you can say 1 + (read "1") and the compiler will know that you must want to read "1" as a number and does that!
- deleted 13y ago[deleted]
- platz 13y agoThat kind inference only works because + is defined to work on Nums only (importing only prelude). You don't even need the initial 1. A nice trick but these are rather small details.
- dllthomas 13y agoYeah, I most commonly hit "oh, I need to annotate that" when I'm building some expression piece by piece in ghci, and so effectively what I'm doing with that value is "print it, as appropriate to the type" - which doesn't tell us much about what type it is.
- tel 13y agoIt's also pretty easy and useful to step out of the HM, inferable fragment using any number of popular language extensions. I'm not arguing that it's a problem, but it's disingenuous to suggest that anything resembling all code can be type-inferred.
- asdasf 13y agoI don't think so. We are talking about haskell after all, not haskell + experimental ghc extensions. And which popular extensions break type inference anyways?
- tel 13y agoRankNTypes are pretty popular in libraries and break total inference. You don't need to enable the extension personally to suffer it either.
- TylerE 13y agoWith the caveat that the compiler can come up with A consistent inferred typing, but it may not be the exact type you had in mind, especially when dealing with numerics. This is very rarely a problem, but in some cases may result in less optimized code than might be possible with a stricter annotation.
- deleted 13y ago[deleted]
- jarrett 13y agoI'm admittedly new to the language, but my convention has been as follows: Declare types of all named functions (i.e. not lambdas). This serves two purposes. First, it makes your code more self-documenting. When I look at a function, probably the first thing I want to know is: "What are its parameters?" Type declarations on functions give you a trustworthy and highly readable answer to that question. Second, it makes type errors easier to understand. If you don't explicitly declare types, the compiler will perform type inference. When your code has a type error, the compiler can infer a nonsensical type for a function, yielding a hard-to-understand error message. If your function has a type declaration, the error message is more likely to point you to where your actual mistake is. Rarely declare types on anything that's not a top-level function definition. For example, if I want to call (foo (bar baz)), I don't need to add separate type declarations to baz, (bar baz), and (foo (bar baz)), even though each quite possibly has a different type. On the other hand, if you want to remind yourself of the type of some inner expression, or you think it'll make the type errors more readable, you can add the declaration. It won't hurt you.
- ixmatus 13y agoI've gotten in the habit of explicitly declaring the types of everything I can. As you already mentioned it's a form of (excellent) documentation that I find myself missing in many languages - when writing Python I get frustrated because I have to go dig or debug the type of a value when in Haskell I can simply look for the type declaration (happily Python I think is considering type annotations). If you use Emacs, haskell-mode and ghc-mod + ag or grep have some awesome features for finding type definitions in source, querying hoogle, and lambdabot style de-sugaring and queries. While type inference is cool, it's only really useful when I'm playing inside GHCi. Also - it can often improve the quality of a program a lot by thinking about your types first, declaring them, then filling out the function definitions (that is often how I do it).
- dllthomas 13y agoOn the flip side, I tend to declare types mostly at the top level. It's nice to be able to change just a few types and have everything else work itself out. There are times it doesn't work and I don't hesitate to add more type annotations then, and when I get weird type errors my first response is go through and decorate it piece by piece.