5 ms·
Last sentence covers it well: > Another way to say this is that you should avoid type parameters until you notice that you are about the write the exact same c
by enw 5y ago
Last sentence covers it well:
> Another way to say this is that you should avoid type parameters until you notice that you are about the write the exact same code multiple times.
(The above will make design pattern astronauts shudder)
- eru 5y agoIt will also make eg Haskeller's shudder. Haskell (and languages with parametric polymorphism in general) can give you lots of guarantees for free when using generic types. Even if at runtime you only ever use your code with one specific type. See eg https://bartoszmilewski.com/2014/09/22/parametricity-money-for-nothing-and-theorems-for-free/ https://bartoszmilewski.com/2014/09/22/parametricity-money-f... To give a super simple example: if in Haskell you see a function with type 'a -> a', you know that it can only be the identify function, because it's generic over 'a', so the code can't do anything specific. In contrast, if you see something like 'float -> float' almost anything can happen (that doesn't involve side-effects). It might be identity, it might be sine, it might be square-roots, etc.
- lgas 5y agoWell, technically `float -> float` is still the identity function, but your point stands for `Float -> Float`.
- eru 4y agoIn my defense, I used pseudo-code that just happens to look a bit like Haskell. ;)
- Dylan16807 5y ago> To give a super simple example: if in Haskell you see a function with type 'a -> a', you know that it can only be the identify function, because it's generic over 'a', so the code can't do anything specific. So I can't have any conditionals or pattern matching based on a parameter's type, or provide default implementations of any functions?
- simiones 5y agoIn Haskell, you can have conditionals/pattern matching on a parameter's type, in the range of the declared types. For example, if you have a parameter of type `Int | Char`, you can pattern match to see if it's Int or Char. But if it's type is completely unbound, you can't do anything with it except pass it around. There is support for reflection, but you have to explicitly ask for it, using Typeable or Data as far as I understand. That is, your function signature still has to constrain the type parameter to be an instance of Typeable or Data (a "reflectable type").
- eru 4y agoExactly! Thanks for saving me the explanation. And almost any type you care about is an instance of Typeable or Data. And your own types can get those instances for free from the compiler, if you ask for them.
- chowells 4y agoCorrect. And this is good. It's what makes Haskell so powerful. You can look at a type and immediately know a huge number of rules its implementation must follow. And even better, the type is machine checked. So unlike prose documentation, it can never lie to you.
- tsimionescu 5y agoThe guarantees in Haskell (and I guess the MLs as well?) come from a much tighter restriction than other languages put on parametric types. For most other languages that support generics/parametric polymorphism, a type like 'a -> 'a would actually be closer to Typeable a => a -> a in Haskell, which can be an infinity of functions. That is, in Go I can easily write something like: func silly[T any](x T) T { if reflect.TypeOf(x).Kind() == reflect.Int64 { var y any = int64(17) return y.(T) } return x } EDIT: In Java or C#, I can even do it without reflection: public static <T> T silly(T x) { if (x instanceof Integer) { return (T)(Integer)17; } return x; }