我想使用Debug.Trace.trace來找出一個函數被評估多少次,並看到一些令人驚訝的結果。在這些表達式的評估中奇怪的重用
ghci> import Debug.Trace
ghci> let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
(Eval'd!
6, Eval'd!
6)
ghci> let x = (trace " Eval'd!" (* 2)) 3 in x `seq` (x, x)
Eval'd!
(Eval'd!
6, Eval'd!
6)
ghci> let x = (trace " Eval'd!" (* 2)) (3 :: Int) in (x, x)
(Eval'd!
6,6)
我做的是Eval'd
是爲(* 2)
功能的各評價一次印刷的假設。這是一個正確的假設嗎?
其次,爲什麼該功能曾多次打印過?我懷疑x
屬於某種未指定類型的Num
類型類型與它有關,因爲第三種情況有效,但我不能想到解釋。
(x, x) :: Num a => (a, a)
保證元組的兩個元素具有相同的值,就像(x, x) :: (Int, Int)
一樣多,那麼爲什麼eval是x
兩倍?
UPDATE:
其實我曾以爲的(x, x)
類型是Num a => (a, a)
。但它顯然是(x, x) :: (Num t, Num t1) => (t, t1)
。
爲什麼GHC沒有意識到t ~ t1
在這裏?我懷疑這與我的問題的答案有關。
我想我明白你的意思是'let x = 3' =>(x,x)::(Int,Integer)=>沒有類型錯誤。所以'x'和'x'不一定是相同的類型,因爲可以傳遞不同的'Num'字典。 有趣。 – obadz
@obadz,進一步混淆事項,使某些類型系統擴展關閉讓泛化,迫使二者具有相同的類型(除非你給類型簽名)。儘管如此,我不知道這是否會改變GHCi。 – dfeuer
@dfeuer哦,呵呵,這就是爲什麼把它放在一個文件中改變它,我應該解釋一下。 –