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

时间:2016-03-12 10:35:27

标签: haskell recursion tree

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

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链接指向the code file。我尽可能地隔离了代码。这是另一个file1,使用以下命令读取以运行代码:

runghc code.hs 30000000.0 20000.0< FILE1.TXT

2 个答案:

答案 0 :(得分:1)

不是答案(无限循环的问题前提似乎不正确),但风格建议 - 评论时间太长。

首先,您可能希望将其设为plugins { id "org.jruyi.thrift" version "0.3.1" } apply plugin: 'idea' apply plugin: 'java' apply plugin: 'maven' apply plugin: "org.jruyi.thrift" group 'com.peernova' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { compile files('/usr/local/lib/thrift-0.9.2.jar') compile 'org.slf4j:slf4j-log4j12:1.7.12' testCompile group: 'junit', name: 'junit', version: '4.11' //compile files("$buildDir/classes/main") { builtBy 'compileThrift' } } def generatedDir = "$buildDir/generated-sources/thrift" compileThrift { thriftExecutable "/usr/local/bin/thrift" //sourceDir "src/main/thrift" sourceDir "$buildDir/../../../lib/service_api" createGenFolder false } task thrift(type: Exec) { commandLine '/usr/local/bin/thrift' } compileJava { dependsOn 'compileThrift' } task(run_server, dependsOn: 'classes', type: JavaExec) { if ( project.hasProperty("appArgs") ) { args Eval.me(appArgs) } main = 'com.apple.project.servicehandlers.server' classpath = sourceSets.test.runtimeClasspath } idea.module.sourceDirs += file("build/generated-sources/thrift") (没有理由增加一层懒惰)。

newtype

其次,对于更容易理解的解决方案,IMO更倾向于实施newtype FlipTree a b = FlipTree (Tree b a) 而不是foldMap;它使语义更清晰。折叠这种结构的方法有多种,最合理的似乎是

foldr

其中外部 foldMap f (FlipTree (Tree _ s [])) = f s foldMap f (FlipTree (Tree _ s children)) = f s <> foldMap (foldMap f . FlipTree) children 在子项列表上折叠,再次使用foldMap作为折叠映射foldMap。现在,如果你想手动将它转换为FlipTree等价物,你基本上只需要穿过参数。

foldr

现在,可能该实例并未实际提供所需的行为,因此请告诉我们您希望它的行为方式!

答案 1 :(得分:0)

原来这个定义是100%正确的。不需要的行为是由其余代码引起的。但是,无论如何,感谢stackoverflow社区始终在那里。