从Int-> Int的递归方案?

Con*_*inn 0 haskell catamorphism anamorphism recursion-schemes

文件夹标识为

foldr (:) []
Run Code Online (Sandbox Code Playgroud)

更一般而言,通过折叠,您可以销毁结构并以汇总值结束,或者以使结构以相同的输出结构结束的方式注入结构。

[Int] -> [Int][Int] -> Int[Int] -> ?

我想知道unfoldr / l是否具有相似的身份。

我知道如何得到

Int -> [Int]

与展开/安娜。

我正在寻找某种方式

Int -> Int

递归方案。

dup*_*ode 5

从您关于阶乘的评论中可以看出,我们可以注意到自然数可以视为递归数据结构:

data Nat = Zero | Succ Nat
Run Code Online (Sandbox Code Playgroud)

递归方案机制而言,相应的基函是:

data NatF a = ZeroF | SuccF a
    deriving (Functor)
Run Code Online (Sandbox Code Playgroud)

NatF但是,与是同构的Maybe。既然如此,递归的方案便利地使Maybe的基函子Natural从型。例如,这是ana专门用于Natural

ana @Natural :: (a -> Maybe a) -> a -> Natural
Run Code Online (Sandbox Code Playgroud)

我们可以用它来写以下内容的身份Natural

{-# LANGUAGE LambdaCase #-}

import Numeric.Natural
import Data.Functor.Foldable

idNatAna :: Natural -> Natural
idNatAna = ana $ \case
    0 -> Nothing
    x -> Just (x - 1)
Run Code Online (Sandbox Code Playgroud)

我们只是给了余代数anaprojectNaturalproject在于解开递归结构中的一层的功能。就递归方案词汇而言,ana project身份是展开的,cata embed也是身份折叠的。(特别是,projectfor列表是unconsfrom的Data.List,除了它使用ListF代替编码Maybe。)

顺便说一下,阶乘函数可以表示为自然的同态(如该问题结尾处的注释所指出的)。我们还可以根据递归方案来实现

fact :: Natural -> Natural
fact = para $ \case
    Nothing -> 1
    Just (predec, prod) -> prod * (predec + 1)
Run Code Online (Sandbox Code Playgroud)

para在每个递归步骤中,都会提供要折叠结构的其余部分(如果我们要折叠一个列表,那将是它的尾部)。在这种情况下,我调用了这样提供的值,predec因为在n从底部到顶部的第-递归步骤中predecn - 1

请注意,如果您碰巧的话,user11228628的同胚可能是更有效的实现。(不过,我还没有对它们进行基准测试。)