If you're familiar with languages like Java, C# or C++ and the concept of generics/templates then this comparison might be useful for you.
Say we have a generic function in C#
public static T DoNothing<T>(T in) { return in; }
To call this function with a float
we can do DoNothing(5.0f)
or if we want to be explicit we can say DoNothing<float>(5.0f)
. That part inside of the angle brackets is the type application.
In Haskell it's the same, except that the type parameters are not only implicit at call sites but also at definition sites.
doNothing :: a -> a
doNothing x = x
This can also be made explicit using either ScopedTypeVariables
, Rank2Types
or RankNTypes
extensions like this.
doNothing :: forall a. a -> a
doNothing x = x
Then at the call site we can again either write doNothing 5.0
or doNothing @Float 5.0