(这不是Haskell问题。)
我有一个递归数据结构。我想在每个级别附加一些额外的信息。这是一个简化的示例,其中我向树的每个级别添加了X
或Y
:
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 ...
(对我来说,TreeF
的定义是不自然的。我宁愿定义data Tree a = Leaf a | Tree a (Tree a) (Tree a)
,但我不知道该如何陈述我的问题。因此,我已经以Base
仿函数(ala Data.Functor.Foldable的形式写)。
Wrap
类型可用于将信息X
或Y
附加到某种数据上。 depth1'
是深度为1的TreeF
,其中Wrap
标志已附加到每个级别(只有一个级别)。 depth2
是深度为2的TreeF
,其中Wrap
标志再次附加在每个级别上(具有两个级别)。
如何创建任意深度的“包裹树”?我应该如何编写其类型签名?这种数据混搭是否有一个类别理论术语?
答案 0 :(得分:6)
您可以使用
Fix (Compose Wrap (TreeF Int))
但我可能不会。如果您确实想走开放式递归路线,那么自己制作Fix
的变体可能是最明智的:
data WrapData = X | Y
data LabeledFix a f = Labeled a (f (LabeledFix a f))
-- ... and then use LabeledFix WrapData (TreeF Int)
但是,更精明的是仍然只是使用普通的旧式封闭式递归。您甚至不必使自己的类型比以前更特殊。只是:
data Tree a = Leaf a | Branch a (Tree a) (Tree a)
-- ... and then use Tree (WrapData, Int)