Consider the following function:
f :: a -> Int
f x = (1 :: Int)
We might say that the type
It's not entirely clear what you want to ask, and what is the practical difference between 1 and 2 in both cases, but from an underlying math perspective:
Parametrically Polymorphic Functions
f
actually has type f :: forall a.a->int
It is a perfectly legal type for a function in typed lambda calculus, which Haskell is based on. It can be something like:
f = λa:Type.λx:a.(body for f)
How do you get Double->Int
from it? You apply it to Double
type:
f Double = (λa:Type.λx:a.(body for f)) Double => λx:Double.(body for f|a=Double)
Haskell does both operations (type abstraction and type application) behind the scene, although it is possible to explicitly state forall
part in the type signature with XExplicitForAll
GHC extension, and explicitly make a Double->Int
instance of f
with type signature:
f_double :: Double -> Int
f_double = f
Higher Kinded Types
Consider a simple type:
data Example = IntVal Int | NoVal
(Yes, it is Maybe Int
).
Maybe
is a type constructor, just like IntVal
is a data constructor. It is exactly the same thing, only 'one level higher', in the sense that Maybe
is applied to Type
, much like IntVal
is applied to Int
.
In lambda calculus, Maybe
has type:
Maybe : Type->Type
Haskell doesn't allow you to get a type from type constructor, but allows you to get a kind (which is just a fancy name for type of type):
:k Maybe
Maybe :: * -> *
So no, Maybe
is not a type: you can't have an object with the type Maybe
. Maybe
is (almost) a function from types to types, like IntVal
is a function from values to values.
We call the result of applying Maybe
to String
as Maybe String
, like we call the result of applying IntVal
to 4
as IntVal 4
.