繁体   English   中英

为什么以下用于创建Tree的Foldable实例的haskell代码导致无限递归?

[英]Why does the following haskell code for creating a Foldable instance of Tree result in infinite recursion?

我正在尝试编写以下创建的Tree类的Foldable实例:

data Tree a b = Tree b a [Tree a b]

但是我想对定义中的类型“ a”进行操作,因此我将包装数据类型转换为Tree中的类型:

data FlipTree a b = FlipTree (Tree b a)

现在编写实际定义,我想到了以下内容:

instance Foldable (FlipTree a) where
  foldr f x (FlipTree (Tree _ s [])) = (f s x)
  foldr f x (FlipTree (Tree _ s children)) =
              let updated_x = (f s x)
                  tqs = (map (\n -> FlipTree n) children) in
              foldl (foldr f) updated_x tqs

但这会在调用foldr时导致无限递归。 我已经花了两天的时间,仍无法弄清我做错了什么?

这是指向代码文件的 lpaste链接。 我尽可能地隔离了代码。 这是另一个file1 ,可使用以下命令读取该文件以运行代码:

runghc code.hs 30000000.0 20000.0 <file1.txt

不是答案(无限循环的前提条件似乎并不正确),而是风格上的建议–评论时间太长。

首先,你可能想使这个newtype (没有理由有懒惰的一个额外层)。

newtype FlipTree a b = FlipTree (Tree b a)

其次,对于一个更容易理解的解决方案,它倾向于使IMO更可取的是实现foldMap而不是foldr 它使语义更清晰。 有多种方法可以折叠此结构,最合理的方法似乎是

  foldMap f (FlipTree (Tree _ s [])) = f s
  foldMap f (FlipTree (Tree _ s children))
             = f s <> foldMap (foldMap f . FlipTree) children

其中,外部foldMap折叠在foldMap列表上,再次将foldMap用于FlipTree用作折叠映射。 现在,如果要手动将其转换为等效的foldr ,则基本上只需要遍历该参数。

  foldr f x (FlipTree (Tree _ s children))
             = f s . flip (foldr $ flip (foldr f) . FlipTree) children $ x

现在,可能该实例实际上并未提供所需的行为,所以请告诉我们您希望它如何表现!

原来定义是100%正确的。 不必要的行为是由其余的代码引起的。 但是无论如何,都要感谢stackoverflow社区一直存在。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM