3 ms·
I'm going to note that even if Go added some kind of parametric polymorphism at this point, it still wouldn't have the same advantages as parametric polymorphis
by andolanra 13y ago
I'm going to note that even if Go added some kind of parametric polymorphism at this point, it still wouldn't have the same advantages as parametric polymorphism in Haskell and related languages. In Go, you can branch on types at runtime, so in a hypothetical generic Go, you could write something which appears to only ever return its argument, but does something special if the argument is of a particular type:
func<T> id(t T) T {
switch t := T.(type) {
case int: return t + 1;
default: return t;
}
}
The ability to examine on types at runtime can enable some interesting programs, but it also means that you don't get guarantees like you do in languages like Haskell. An example of this biting someone in practice is this blog post[1], where the author reasoned that because a library function expected an io.Reader, all it would do is use the Read method as exposed by Reader. In reality, though, the function was able to branch on the type and determine whether it also exposed a Close method, and called that if it could. That kind of feature destroys the useful static guarantees provided by parametric polymorphism in other languages like ML or Haskell.
[1]: http://how-bazaar.blogspot.co.nz/2013/07/stunned-by-go.html http://how-bazaar.blogspot.co.nz/2013/07/stunned-by-go.html
- tel 13y agoAs a second addendum, while andolanra's comment is completely true, you can actually do type dispatch in Haskell using the Typeable machinery; however, the type system requires that you mark your types when this occurs. what :: Typeable a => a -> a Here `what` is no longer guaranteed to be `id`. Instead, we can translate it like this what :: (a -> TypeRep) -> a -> a where `TypeRep` is, as it sounds, a representation of the type of a returned dynamically. This means that we can do careful coercions to, say, be `id` unless `a` is `Int` in which case we add `1`. Suffice to say that the degree of guarantee breaking that this kind of code invites makes Typeable a very specialized library that's almost never recommended without a "unless you really know what you're doing" kind of warning.
- chimeracoder 13y ago> In Go, you can branch on types at runtime, so in a hypothetical generic Go, you could write something which appears to only ever return its argument, but does something special if the argument is of a particular type I'm not sure why you bring this up - nearly every language that enables reflection lets you do this, including Haskell[0]. No decidable static type system can ensure correct semantics for all use cases, including even badly written code[1]. [0] And you don't even need reflection to do this, per se; it just makes it more convenient. [1] One could design a static type system that did, but it would be undecidable.
- tel 13y agoParametricity is definitely not impossible to violate, but it's generally morally correct to assume it mostly holds in Haskell. Parametric polymorphism helps make that workable. Further, type classes help to tag code that does use reflection. You can always get around things, but languages that make a strong commitment to keeping reasoning as a priority are qualitatively different from those that do not.