當我有以下代碼:Haskell中'where'子句中的內容只計算一次嗎?
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n
多少次被稱爲FUNC2功能?只有一次,在where子句中?還是每次使用m時都會重新計算一次?
當我有以下代碼:Haskell中'where'子句中的內容只計算一次嗎?
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n
多少次被稱爲FUNC2功能?只有一次,在where子句中?還是每次使用m時都會重新計算一次?
也許這是不是在所有(懶惰的快樂)評估 - 但如果它是,它應該只計算一次 - 如果你喜歡,你可以嘗試一下trace
:
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n
func2 n = trace "called..." [n]
這裏在GHCI一個例子:
λ> func 3
called...
[3,1,3,0,3]
這裏是一個,你看,它可能不會被調用(直到你最後需要對其進行評估):
λ> let v = func 4
λ> v
called...
[4,1,4,0,4]
見:首先它不叫 - 只有當你最終評估v
(打印出來),你得到的通話。只要你沒有禁用單態限制
卡斯滕的答案(該值將最多一次來計算)是正確的。如果你有,那麼m
可能有一個多態類型推斷,涉及類型的類,然後m
是不是一個真正的標準值,而是一個功能,需要一個類型的類字典併產生價值。考慮這個例子。
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n -- m :: Monad t => t a (where n :: a)
func2 n = trace "called..." (return n) -- func2 :: Monad t => a -> t a
然後評估在ghci中打印func 3
called...
[3,1called...
,3,0called...
,3]
要添加到@ Carstan的和@Reid巴頓的回答,這也取決於你是否正在運行的編譯代碼或沒有,例如:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Debug.Trace(trace)
func n = m ++ [1] ++ m ++ [0] ++ m
where m = func2 n -- m :: Monad t => t a (where n :: a)
func2 n = trace "called..." (return n)
main = let xs = func 3 :: [Int]
in print xs
ghci
正在運行main
打印出called
3次。但是,編譯時,使用-O2
時僅打印出called
一次。 (測試了7.10.2)
你與優化編譯啓用我只有7.10.1,但我看到'叫什麼名字? '印刷3次編輯以及何時但可以肯定的優化還可以在一般的影響這種行爲 –
是 - 。我和-02編譯我會澄清答案。 – ErikR
感謝 - 非常好的問題 - 我確實沒想到這裏的這個在所有。這真的很難給上Haskell的正確答案,當涉及到這樣的細節 - 通常有呈現你的直覺毫無價值的擴展:*( – Carsten