npo*_*cop 11 recursion haskell catamorphism recursion-schemes
我发明了一种递归方案,这种方法是对同态性的推广.折叠具有catamorphism的数据结构时,您无法访问子项,只能访问折叠的子结果:
{-# 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
Run Code Online (Sandbox Code Playgroud)
折叠功能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
Run Code Online (Sandbox Code Playgroud)
现在,可以结合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
Run Code Online (Sandbox Code Playgroud)
processTerm varArgs为每个标识符返回它在不同控制路径上接收的实际参数列表.例如,bar (foo 2) (foo 5)它返回fromList [("foo", [2, 5])]
请注意,在此示例中,结果与其他结果统一组合,因此我希望使用派生实例存在更简单的实现Data.Foldable.但总的来说并非如此,因为它phi可以运用其内部结构的知识,ExampleFunctor以可折叠的方式组合"子项目"和"子结果".
我的问题是:我可以processTerm使用现代递归方案库中的库存函数来构建recursion-schemes/Data.Functor.Foldable吗?
Pet*_*lák 12
折叠使得它"吃论证并保持它"也称为共生.事实上,你的功能可以很容易地使用表达递归的方案为
cataWithSubterm :: Functor f => (Fix f -> b -> a) -> (f a -> b) -> Fix f -> b
cataWithSubterm f g = para $ g . fmap (uncurry f)
Run Code Online (Sandbox Code Playgroud)
而且,如果我们提供(,)给cataWithSubterm你processTerm,我们得到
cataWithSubterm (,) :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b
Run Code Online (Sandbox Code Playgroud)
这是para专门为Fix:
para :: Functor f => (f (Fix f, b) -> b) -> Fix f -> b
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
507 次 |
| 最近记录: |