在递归数据类型的每个级别附加附加信息?

Jef*_*own 1 haskell recursive-datastructures category-theory fixpoint-combinators

(这不是一个特别的Haskell问题。)

我有一个递归数据结构。我想在每个级别附加一些额外的信息。这是一个简化的示例,其中我在树的每个级别上添加XY

import Data.Functor.Foldable

data Wrap a = X a | Y a
  deriving Show

data TreeF a b = Leaf a | TreeF a b b
  deriving Show

depth1 :: Wrap (TreeF Int ())
depth1 = X (Leaf 1)

depth2 :: Wrap (TreeF Int (Wrap (TreeF Int ())))
depth2 = Y (TreeF 1 (X $ Leaf 1) (Y $ Leaf 1))

-- depthInfinity :: Fix something something ...
Run Code Online (Sandbox Code Playgroud)

TreeF对我来说,定义是不自然的。我宁愿定义data Tree a = Leaf a | Tree a (Tree a) (Tree a),但我不知道是否要提出问题。因此,我以Base函子ala Data的形式编写了它.Functor.Foldable。)

Wrap类型可用于附加信息XY某种数据。depth1'是深度为1 TreeFWrap标志,其中每个级别都附加了标志(只有一个级别)。depth2是深度2,TreeF在该深度中,该Wrap标志再次附加在每个级别上(具有两个级别)。

如何创建任意深度的“包装树”?我应该如何编写其类型签名?对于这种数据混搭,是否存在类别理论术语?

Dan*_*ner 6

你可以用

Fix (Compose Wrap (TreeF Int))
Run Code Online (Sandbox Code Playgroud)

但我可能不会。如果您确实想走开放式递归路线,那么自己制造的变体Fix可能是最明智的:

data WrapData = X | Y
data LabeledFix a f = Labeled a (f (LabeledFix a f))
-- ... and then use LabeledFix WrapData (TreeF Int)
Run Code Online (Sandbox Code Playgroud)

但是,甚至更精明的是仍然只是使用普通的旧式递归。您甚至不必使自己的类型比以前更特殊。只是:

data Tree a = Leaf a | Branch a (Tree a) (Tree a)
-- ... and then use Tree (WrapData, Int)
Run Code Online (Sandbox Code Playgroud)