5 ms·
> You definitely do not look at it like minimally using type annotations “only where it adds clarity” because the whole point is that as the code author you don
by jcelerier 8y ago
> You definitely do not look at it like minimally using type annotations “only where it adds clarity” because the whole point is that as the code author you don’t know where clarity is needed. That is for the code reader who has to change your work later on.
Are you serious ? In standard Haskell you can't even add type annotations to bindings, that's how much type annotations are relevant to the language. They're only available in type & function definitions. I seriously doubt that you use
{-# LANGUAGE ScopedTypeVariables #-}
and that all of your code looks like
main =
let (x :: Integer) = 123 in
print $ x
That's literally what you expect C++ programmers to do when you ask them not to use auto, and I've absolutely never seen production Haskell looking like this - common Haskell is much closer to this : https://github.com/ivanperez-keera/haskanoid/blob/master/src/Game.hs https://github.com/ivanperez-keera/haskanoid/blob/master/src....
- mlthoughts2018 8y agoNah. ScopedTypeVariables is extremely commonly used, and Haskell as a language is one where frequent use of extensions is common generally. Saying “you can’t even add type annotations to let bindings” shows a misunderstanding of Haskell, because you can and the way the language accomplishes it is with ScopedTypeVariables. It’s not “special” or “extra” in Haskell, using extension pragmas is just a super common, mundane, every-day thing in Haskell. I should also point out that when you say > “They're only available in type & function definitions.” you are wrong. Firstly, you can (and should almost always) use type annotations for plain values, like pi :: Float pi = 3.14 and e.g. with more complex data constructors like in < https://en.m.wikibooks.org/wiki/Haskell/Type_declarations https://en.m.wikibooks.org/wiki/Haskell/Type_declarations > section on constructor functions. For value constructors that use complex type dynamism in Haskell, like the return value polymorphism in Haskell regular expressions, it’s critical to use type annotations on plain values, because the type annotation actually resolves which of the polymorphic return types will be chosen. Secondly, and more importantly, you can use type annotations on bindings natively in a where clause, and this is a very fundamentally important thing to do, especially for locally defined helper functions. Then you only need ScopedTypeVariables if your helper function needs to involve a generic type constraint from the polymorphism of the outer function declaration, which is vastly more rare. I’d also say the comparison with the types of local variables that tend to be unannotated in Haskell let or where clauses is very disingenuous and it’s actually not similar to the iterator boilerplate example you gave before at all. When all the arguments have well-annotated types, and you use a let or where variable to hold a temporary value, the type is inferred by a reader much more easily than when using auto in C++, and has a direct meaning in terms of the calculation at hand (e.g. it’s not done to reduce boilerplate like auto). For example, if you’re trying to calculate distance between two tuples (x0, y0) and (x1, y1), where the types of those tuple elements are given explicitly just a few lines up, then there is little harm in doing something like where dx = x1 - x0 though it’s still preferable to say e.g. where dx = x1 - x0 :: Float This is emphatically not what you’re doing with auto, because the types are not otherwise locally obvious, and even if they were, a judicious use of typedef / typename saves just as much syntax while being far more descriptive.
- jcelerier 8y agonow let's be serious. A google search for "ScopedTypeVariables" returns 13 300 results. That's minuscule. But well, let's just say that we have a fairly different experience of haskell code. > When all the arguments have well-annotated types, and you use a let or where variable to hold a temporary value, the type is inferred by a reader much more easily than when using auto in C++, and has a direct meaning in terms of the calculation at hand (e.g. it’s not done to reduce boilerplate like auto). ... In (non-generic) c++, function arguments always have types. You can't have `auto` in type declarations (thankfully it should come in C++20) - the comparison stands. I've heard so many reticences to auto like yours from coworkers and interns, and then after three days in a large auto-enabled codebase no one ever did go back to writing unnecessary types.