Wie gehe ich mit dem Typensystem auf Haskell bequem um?

Haskells Typensystem ist mächtig und beliebt für seine mathematische Genauigkeit und logische Solidität. Auf der anderen Seite frage ich mich, warum es nicht so funktioniert, wie es von der Intuition erwartet wird.

Z.B. warum kann nichtInt zu @ konvertiert werdNum aufx3 aberf1 akzeptierenInt gegen die SignaturNum?

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’

Ich wusste, dass man endlich die zugrunde liegende Theorie lernen sollte, z.HM Typ System, um bequem mit dem Typensystem umzugehen, und fand sogar einige nette Schriften, z.1, 2, 3 und4 für die Entmystifizierung. Was würdest du sonst noch empfehlen, wenn du jemals diese Herausforderung gemeistert hast?

@BEARBEITE

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’

Zuerst,x6 muss ein Supertyp von @ gewesen seNum das istNum selbst wennx6 ist mit @ beschriftNum. Die verketteten Typanmerkungen fürNum nachInt von(x6::Int)::Num a => a wird nicht vereint sein, wenn wir dann @ downcax6 vonNum zuInt. Daher ist der erste abgeleitete TypNum vonx6 ist hier unzufrieden.