Haskell 递归方案的库实现

Haskell 递归方案的库实现,haskell,recursion,catamorphism,recursion-schemes,Haskell,Recursion,Catamorphism,Recursion Schemes,我“发明”了一个递归方案,这是一个对亚同态的推广。当使用亚同态折叠数据结构时,您无法访问子项,只能访问折叠的子结果: {-# LANGUAGE DeriveFunctor #-} import qualified Data.Map as M newtype Fix f = Fix { unFix :: f (Fix f) } cata :: Functor f => (f b -> b) -> Fix f -> b cata phi = self where

我“发明”了一个递归方案,这是一个对亚同态的推广。当使用亚同态折叠数据结构时,您无法访问子项,只能访问折叠的子结果:

{-# LANGUAGE DeriveFunctor #-}
import qualified Data.Map as M

newtype Fix f = Fix { unFix :: f (Fix f) }

cata :: Functor f => (f b -> b) -> Fix f -> b
cata phi = self where
    self = phi . fmap (\x -> self x) . unFix
折叠功能
phi
只能访问
self x
的结果,而不能访问原始
x
。所以我添加了一个连接函数:

cataWithSubterm :: Functor f => (Fix f -> c -> b) -> (f b -> c) -> Fix f -> c
cataWithSubterm join phi = self
    where self = phi . fmap (\x -> join x (self x)) . unFix
现在可以有意义地组合
x
self x
,例如使用
(,)

processTerm varArgs
为每个标识符返回它在不同控制路径上接收的实际参数列表。例如,对于
bar(foo 2)(foo 5)
它从列表[(“foo”,[2,5])]返回

请注意,在本例中,结果与其他结果统一组合,因此我希望使用
Data.Foldable的派生实例存在一个更简单的实现。但通常情况并非如此,
phi
可以运用其对
ExampleFunctor
内部结构的了解,以可折叠的方式组合“子项”和“子结果”

我的问题是:我是否可以使用现代递归方案库(如
递归方案/Data.Functor.Foldable
)中的stock函数来构建
processTerm

折叠,使其“吃了参数,也保留了参数”称为。实际上,您的函数可以很容易地用as表示

此外,如果我们像您在
processTerm
中那样向
cataWithSubterm
提供
(,)
,我们将得到

cataWithSubterm (,)  :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b
这正是
para
专门用于
Fix

para                 :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b
查阅
cataWithSubterm (,)  :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b
para                 :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b