I\'m a beginner(ish) in Haskell and I find error message really hard to understand (I guess it comes with time). Anyway, to help me understanding my mistakes, I tried to add int
This should work:
f :: s -> s
f x =
let y = undefined :: s
in y
Just use the normal ::
operator as shown in the above example for type annotation.
Update:
It doesn't seem to work with polymorphic types. But it works with an concrete type.
The following typechecks:
f :: Int -> Int
f x = let m = x :: Int
in m
This produces error:
f1 :: a -> a
f1 x = let m = x :: a
in m
You need the ScopedTypeVariables
extension for this to work, like this:
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. a -> a
f x =
let x' = x :: a
in x'
If you have a type signature like this
f :: a -> a
then it indicates that f
is polymorphic and works for any choice of a
. So f
could be
used at type Int -> Int
, or at type Bool -> Bool
, or at type [Int -> Bool] -> [Int -> Bool]
– whatever you like.
If you have a type annotation like this
x :: a
it means a similar thing, namely that x
should be usable at any type of your choice. But that's not true in your case. The outer function f
is polymorphic, but within the function, x
has to be of the same type a
that the user has chosen for the outer x
. By default, Haskell makes no connection between type variables occurring in different type signatures and annotations. However, you can tell it to do so by enabling the ScopedTypeVariables
extension. Now, by prefixing a -> a
with forall a.
, you can explicitly instruct Haskell to make a
visible as a specific type variable within the definition of f
. If you then annotate x :: a
, it refers to the outer a
rather than a new polymorphic a
.
For anyone who is looking to type annotate the binding instead of the expression - ScopedTypeVariables
allows you to do that too!
f1 = do
let x :: Int = 5
y :: Int <- someMonadicOperation
return $ x + y