我“发明”了一个递归方案,它是变质作用的推广。当您用变形折叠数据结构时,您无法访问子项,而只能获得折叠的子结果:
{-# 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,例如使用(,)
data ExampleFunctor a = Var String | Application a a deriving Functor
type Subterm = Fix ExampleFunctor
type Result = M.Map String [Subterm]
varArgs :: ExampleFunctor (Subterm, Result) -> Result
varArgs a = case a of
Var _ -> M.empty
Application ((Fix (Var var)), _) (arg, m) -> M.insertWith (++) var [arg] m
processTerm :: (ExampleFunctor (Subterm, Result) -> Result) -> Subterm -> Result
processTerm phi term = cataWithSubterm (,) phi term processTerm varArgs为每个标识符返回它在不同控制路径上接收的实际参数列表。例如,对于bar (foo 2) (foo 5),它返回fromList [("foo", [2, 5])]
请注意,在这个示例中,结果与其他结果一致地结合在一起,因此我希望使用派生的Data.Foldable实例存在一个更简单的实现。但通常情况并非如此,因为phi可以运用其对ExampleFunctor内部结构的知识,以无法折叠的方式将“子项”和“子结果”结合起来。
我的问题是:我可以使用来自现代递归方案库(如processTerm )的库存函数来构建recursion-schemes/Data.Functor.Foldable吗?
发布于 2013-08-02 11:33:00
折叠,使它“吃掉并保留它”被称为变质作用。实际上,您的函数可以很容易地使用http://hackage.haskell.org/packages/archive/recursion-schemes/3.0.0.2/doc/html/Data-Functor-Foldable.html表示为
cataWithSubterm :: Functor f => (Fix f -> b -> a) -> (f a -> b) -> Fix f -> b
cataWithSubterm f g = para $ g . fmap (uncurry f)此外,如果我们向(,)提供cataWithSubterm,就像您在processTerm中所做的那样,我们将得到
cataWithSubterm (,) :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b它正是para专门为Fix服务的
para :: Functor f => (f (Fix f, b) -> b) -> Fix f -> bhttps://stackoverflow.com/questions/18013547
复制相似问题