我試圖弄清楚為什么這段代碼沒有按預期作業。
我想創建一個函式run,該函式將某個函式作為輸入并回傳應用于自身的該函式。
run::(t1->t2)->t2
run a = a a
包含的型別應該是通用的,因為我希望它適用于任何事情,但是當我嘗試時我遇到了無限的型別錯誤,我不知道為什么。
uj5u.com熱心網友回復:
你說a :: t1 -> t2。這意味著它的引數應該有型別t1。然后你將它應用到自身,a a. 這意味著它的論點是a。
所以現在我們有了一個等式:引數應該同時具有型別t1(因為它是 的引數a)和型別t1 -> t2(因為它是a):
t1 ~ t1 -> t2
~ (t1 -> t2) -> t2
~ ((t1 -> t2) -> t2) -> t2
~ (((t1 -> t2) -> t2) -> t2) -> t2
~ ...
每一行都是從前一行通過替換t1為它等于的東西,t1 -> t2。沒有有限型別滿足給定的相等性。
uj5u.com熱心網友回復:
如果你想在 Haskell 中撰寫等價于 (λx.xx) (λx.xx) 或 Y 組合器,可以這樣做:
Prelude> newtype F t2 = Wrap {unwrap :: F t2 -> t2}
Prelude> run x = (unwrap x) x
Prelude> :t run
run :: F t2 -> t2
Prelude> run (Wrap run)
^C
Interrupted.
Prelude> myFix f = run (Wrap (\x -> f ((unwrap x) x)))
Prelude> factorial = myFix (\fac n -> if n == 0 then 1 else n * fac (n - 1))
Prelude> factorial 5
120
添加和刪??除 newtype 包裝器在運行時是無操作的。
Haskell 不允許這種沒有dataornewtype包裝器的自參考(“無限”)型別。自動推斷無限型別是可能的,并且不會使型別系統變得比現在更不一致,但無限型別不是很有用,而且它們經常意外地出現在真正不應該進行型別檢查的錯誤代碼中,所以他們被拒絕可能更好。
uj5u.com熱心網友回復:
你寫
run::(t1->t2)->t2
run a = a a
因為a是函式的引數,
a :: t1 -> t2
現在,你申請a到a。的引數a有型別t1,所以我們必須有
a :: t1
唯一有意義的是 ift1與t1 -> t2. 所以這意味著
t1
= t1 -> t2
= (t1 -> t2) -> t2
= ((t1 -> t2) -> t2) -> t2
= ...
那可能是您的無限型別錯誤的來源。我不知道為什么你沒有得到一個更簡單的錯誤,說這t1與t1 -> t2.
所以......你不能在 Haskell 中完全呼叫一個函式。你可以做一些類似的事情,但要小心一些。但是,您如何做到這一點將取決于您要完成的作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/359153.html
