這是我的第一個 Stack Overflow 問題,所以如果我忘記了任何重要資訊,請告訴我,我會添加它!
所以我是 Haskell 的新手,只是在學習型別和類。現在我已經宣告了 1 個型別和 2 個函式:
data Nat = Zero | Succ Nat
add :: Nat -> Nat -> Nat
add Zero n = n
add (Succ m) n = Succ (add m n)
mult :: Nat -> Nat -> Nat
mult Zero _ = Zero
mult (Succ m) n = add n (mult m n);
呼叫第一個函式時,我可以全面評估它并了解 Haskell 如何處理它。像這樣:
> 2 1 = 3
>
> add (Succ (Succ Zero)) (Succ Zero)
>
> Succ (add (Succ zero)) (Succ Zero))
>
> Succ (Succ (add Zero (Succ Zero))
>
> Succ (Succ (Succ Zero))
但我無法理解這對mult函式來說是怎樣的。對我來說,這看起來像是一個無限回圈的添加。誰能向我解釋如何mult評估該功能?
uj5u.com熱心網友回復:
因為mult您可以用與您所做的非常相似的方式進行評估add- 通過重復替換名稱的定義。只是需要更長的時間。
> 2 * 2 = 4
mult (Succ (Succ Zero)) (Succ (Succ Zero))
-- Substituting second case of mult. m = Succ Zero, n = Succ (Succ Zero)
add (Succ (Succ Zero)) (mult (Succ Zero) (Succ (Succ Zero))
-- Substituting second case of mult. m = Zero, n = Succ (Succ Zero)
add (Succ (Succ Zero)) (add (Succ (Succ Zero)) (mult Zero (Succ (Succ Zero))))
-- Substituting FIRST case of mult, because the first parameter is now Zero.
add (Succ (Succ Zero)) (add (Succ (Succ Zero)) Zero)
-- And now we have nothing but addition left.
-- Substituting the inner add:
add (Succ (Succ Zero)) (Succ (add (Succ Zero) Zero))
add (Succ (Succ Zero)) (Succ (Succ (add Zero Zero)))
add (Succ (Succ Zero)) (Succ (Succ Zero))
-- Substituting the outer add:
Succ (add (Succ Zero) (Succ (Succ Zero)))
Succ (Succ (add Zero (Succ (Succ Zero))))
Succ (Succ (Succ (Succ Zero)))
Q.E.D
證明mult遞回最終會結束的關鍵在于,每次遞回呼叫都比前一次“小”——憑借“去除”一層Succ.
uj5u.com熱心網友回復:
模式幾乎與 for 完全相同add,但 withadd n而不是Succ作為在前面慢慢積累的東西。在這里,它們是并排的;我已經在減少中替換了你的第一個Succ Zero,以使相似之處更加明顯:nadd
add (Succ (Succ Zero)) n mult (Succ (Succ Zero)) n
Succ (add (Succ zero) n) add n (mult (Succ Zero) n)
Succ (Succ (add Zero n)) add n (add n (mult Zero n))
Succ (Succ n) add n (add n Zero)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/363878.html
上一篇:如何讓這個函式被懶惰地評估
下一篇:如何針對已編譯的包運行GHCi?
