或者具體而言,爲什麼我們使用foldr來編碼列表和迭代來編碼數字?爲什麼我們使用摺疊來編碼數據類型作爲函數?
對不起,我很想知道如何命名我想問的事情,所以我需要首先給出一些說明。這從this C.A.McCann post吸引很大,只是不完全滿足我的好奇心,我也會用rank-n類型和無限懶惰的東西handwaving問題。
一個編碼數據類型作爲功能的方法是創建接收用於每種情況下一個參數是「圖案匹配」功能,每個變元爲接收對應於該構造,並返回一個相同的值的所有參數的函數結果類型。
這一切工作達到預期的非遞歸類型
--encoding data Bool = true | False
type Bool r = r -> r -> r
true :: Bool r
true = \ct cf -> ct
false :: Bool r
false = \ct cf -> cf
--encoding data Either a b = Left a | Right b
type Either a b r = (a -> r) -> (b -> r) -> r
left :: a -> Either a b r
left x = \cl cr -> cl x
right :: b -> Either a b r
right y = \cl cr -> cr y
然而,漂亮的類比模式匹配擊穿遞歸類型。我們也許會做這樣的事情
--encoding data Nat = Z | S Nat
type RecNat r = r -> (RecNat -> r) -> r
zero = \cz cs -> cz
succ n = \cz cs -> cs n
-- encoding data List a = Nil | Cons a (List a)
type RecListType a r = r -> (a -> RecListType -> r) -> r
nil = \cnil ccons -> cnil
cons x xs = \cnil ccons -> ccons x xs
,但我們不能在Haskell寫那些遞歸類型的定義!通常的解決方案是強制cons/succ案例的回調應用於所有級別的遞歸,而不僅僅是第一個(即寫一個fold/iterator)。在這個版本中,我們使用的返回類型r
在遞歸類型是:
--encoding data Nat = Z | S Nat
type Nat r = r -> (r -> r) -> r
zero = \cz cf -> cz
succ n = \cz cf -> cf (n cz cf)
-- encoding data List a = Nil | Cons a (List a)
type recListType a r = r -> (a -> r -> r) -> r
nil = \z f -> z
cons x xs = \z f -> f x (xs z f)
雖然這個版本的作品,它使得定義一些功能更難。例如,如果你可以使用模式匹配,編寫一個列表的「尾部」函數或數字的「前輩」函數是微不足道的,但如果你需要使用摺疊,則會變得棘手。
所以到我真正的問題:
我們怎樣才能確保在使用褶皺編碼是爲假想「模式匹配編碼」一樣強大?有沒有辦法通過模式匹配採取任意函數定義,並將其機械轉換爲僅使用摺疊的模式? (如果是的話,這也將有助於使棘手的定義,例如尾巴或與foldl在foldr相似的條款少神奇)
爲什麼不Haskell的類型系統允許在「模式匹配」所需的遞歸類型編碼?。是否有隻允許通過
data
定義的數據類型的遞歸類型的原因?模式匹配是直接使用遞歸代數數據類型的唯一方法嗎?它是否與類型推理算法有關?
我會在這裏留下這個:http://www.haskell.org/pipermail/haskell-cafe/2010-November/085897.html – melpomene
@melpomene:嗯,它看起來像它出問題#2 - 你可以在Haskel中做到這一點,但你需要使用newtypes來獲得遞歸性。現在我只需要看看你鏈接的那些論文是否也回答#1 :)(順便說一句,你的[鏈接](http://www.haskell.org/pipermail/haskell-cafe/2010-November/085897.html)被拷貝粘貼怪異) – hugomg
儘管前身爲納特是硬的,將是'O(1)'(我認爲這是更有效的比二進制版本的計算機通常使用。) – PyRulez