簡體   English   中英

原始遞歸和變態之間有什么聯系?

[英]What is the connection between primitive recursion and catamorphisms?

使用以下自然數的變態,我可以實現各種算術算法,而無需處理遞歸:

cataNat :: b -> (b -> b) -> Natural -> b
cataNat zero succ = go
  where
    go n = if (n <= 0) then zero else succ (go (n - 1))

fib :: Natural -> Natural
fib = fst . cataNat (0, 1) (\(a, b) -> (b, a + b))

cataNat在我看來類似於原始遞歸。 至少它的每個應用程序似乎都保證終止,無論提供了zerosucc的哪種組合。 在每次迭代中,整個問題都被最小/最簡單的問題實例分解。 因此,即使它在技術上不是原始遞歸,它似乎也具有同樣的表現力。 如果這是真的,則意味着變態不足以表達一般遞歸。 我們可能需要一個hylomorphism。 我的推理是否正確,也就是說,是否對任何類型的變質都成立,而不僅僅是自然數?

原語遞歸直接對應於一個paramorphism。

您是正確的,變質具有與異質性等效的理論能力,但是在操作方面它們可能在重要方面有所不同。 例如,讓我們將 go 列在列表中,而不是 Nats。

cata :: b -> (a -> b -> b) -> [a] -> b
cata = flip foldr -- I'm lazy, but this argument order makes a bit more sense for this example

para :: b -> (a -> [a] -> b -> b) -> [a] -> b
para z _ []     = z
para z f (x:xs) = f x xs (para z f xs)

-- Removes the first element from the list which is equal to the other argument
delete1 :: Eq a => a -> [a] -> [a]
delete1 x xs = cata (const []) (\el k found -> if not found && el == x then k True else el : k found) xs False

-- Removes the first element from the list which is equal to the other argument
delete2 :: Eq a => a -> [a] -> [a]
delete2 x xs = para [] (\el raw processed -> if el == x then raw else el : processed) xs

看看delete1delete2相比有多尷尬。 您不僅必須通過使 cata 的結果為cata來扭曲您的邏輯,而且還有非常實際的運營成本。 您必須在找到匹配元素后遍歷列表中的所有內容,並重新創建所有(:)構造函數。 這可能會在效率上產生顯着的成本。 相比之下, delete2找到目標元素時,可以只使用列表的現有尾部作為剩余部分,甚至無需查看它。 當然,大多數foldr使用(現實世界,不是這個例子)不會產生 function 並且不想訪問列表的未處理尾部。 對他們來說,僅僅因為傳遞更少的數據,變質將稍微更有效率。

所以就理論能力而言,它們是等價的。 在操作方面,每個都有一個用途,盡管變質更為常見。

對於更一般的概念的一些擴展,請參閱遞歸方案庫。 它使用了一種看起來完全不同的想法,以便它可以抽象出具有不同形狀的數據類型,而不需要為每個可以應用的數據類型使用不同的cata / para類型。 但這實際上只是打包相同想法的另一種方式,並且還涵蓋了其他類型的態射,包括多利基(甚至可能無用)的態射。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM