Como lidar confortavelmente com o sistema de tipos em Haskell?

O sistema de tipos de Haskell é poderoso e apreciado por seu rigor matemático e solidez lógica; por outro lado, algo tão ingênuo como abaixo me faz pensar por que ele não funciona como o esperado pela intuição?

Por exemplo. por que nãoInt ser convertido paraNum emx3 masf1 aceitarInt contra a assinaturaNum?

Prelude> let x1 = 1
Prelude> :t x1
x1 :: Num a => a

Prelude> let x2 = 1 :: Int
Prelude> :t x2
x2 :: Int

Prelude> let x3 = (1 :: Int) :: Num a => a
Couldn't match expected type ‘a1’ with actual type ‘Int’

Prelude> let f1 :: Num a => a -> a; f1 = id
Prelude> :t f1 (1 :: Int)
f1 (1 :: Int) :: Int

Prelude> let f2 :: Int -> Int; f2 = id
Prelude> :t f2 1
f2 1 :: Int

Prelude> let f3 :: Num a => a -> Int; f3 = id

Prelude> let f4 :: Num a => Int -> a; f4 = id
Couldn't match type ‘a’ with ‘Int’

Eu sabia que alguém deveria finalmente aprender a teoria subjacente, p.Sistema tipo HM para lidar confortavelmente com o sistema de tipos e até encontrou alguns textos interessantes, por exemplo1, 2, 3 e4 por desmistificar isso. O que mais você gostaria de recomendar se alguma vez cruzasse e vencesse esse desafio?

@EDITAR

Prelude> let f5 x5 = x5::Int
Prelude> :t f5
f5 :: Int -> Int

Prelude> let f6 x6 = x6::Num a => a
Couldn't match expected type ‘a1’ with actual type ‘t’

Primeiro,x6 deve ter sido um supertipo deNum isso éNum quandox6 é do tipo anotado comNum. No entanto, as anotações de tipo concatenadas paraNum depois deInt do(x6::Int)::Num a => a não será unido se então abatermosx6 deNum paraInt. Portanto, o primeiro tipo inferidoNum dox6 está insatisfeito aqui.