> 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)
> 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)
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-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.
So I can't have any conditionals or pattern matching based on a parameter's type, or provide default implementations of any functions?
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").
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.
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;
}