我将实现一个函数,该函数接收Integer
并输出一个懒惰的,无限的互质Integer
列表。
coprime 2 = [1,3..]
coprime 3 = [1,2,4,5,7,8,....]
我希望这些列表会被多次访问,所以我希望它们的值存储为CAF。 (如果我错误地使用该术语,请原谅我)好吧,这很好,因为这将由编译器自动完成(我认为)。但是保证具有相同输出的不同输入呢?例如:
coprime 2 = [1,3..]
coprime 4 = [1,3..]
如何确保这两种模式调用相同的CAF,以便不必重新计算结果?
我的第一个想法是尝试实现coprime
,以便coprime 2
和coprime 4
实际上使用相同的参数调用本地函数。一个最小的例子:
coprime n
| n == 4 = realcoprime 2
| otherwise = realcoprime n
where
realcoprime n = .....
但是,对coprime
的所有来电是否都与{{1}}相关联的CAF值相同?如果是这样,它们不会过早收集垃圾,因为它们不在全球范围内吗?
答案 0 :(得分:2)
一般来说,函数无法记忆(at least in general they can't)。如果你希望Haskell记忆函数,这意味着它必须在运行时保持已经看到的输入字典及其相应的输出,但是函数调用涉及在这个字典中查找!
但是,有些图书馆提供此功能:例如memoize
和data-memocombinators
。例如,使用后者,我可以用
import com.android.build.gradle.internal.pipeline.TransformTask
def deleteDuplicateJniFiles() {
def files = fileTree("${buildDir}/intermediates/exploded-aar/com.facebook.react/react-native/0.31.0/jni/") {
include "**/libgnustl_shared.so"
}
files.each { it.delete() }
}
tasks.withType(TransformTask) { pkgTask ->
pkgTask.doFirst { deleteDuplicateJniFiles() }
}
然后关于你的第二个问题,现在它 适合制作第二个函数,最终调用第一个函数。
答案 1 :(得分:0)
我撤回了我接受的'来自@ Alec的回答是因为我发现上面显示的方法只会记住coprime
函数的输入。正如问题中所述,我需要在记忆之前对输入参数进行一些简化,否则我将为多个参数存储完全相同的数据。所以这是我第一次尝试解决这个问题:
cprimes :: [Integer] -> [Integer]
cprimes relnums = cprime' (mySimplify relnums)
where
mySimplify relnums = ....
cprimes' = (Memo.list Memo.integral) cprimes''
cprimes'' relnums = ....
但是,这里的记忆似乎至少不在全局背景中进行。使用相同的参数调用cprimes
时,将重新计算结果。我怀疑结果是在对cprimes
的一次调用中被记忆,然后进行了垃圾收集,因为cprimes'
块中定义了where
。
这是我第二次尝试解决方法:
cprimes :: [Integer] -> [Integer]
cprimes relnums = cprimetables (mySimplify relnums)
cprimetables = (Memo.list Memo.integral) cprimes'
where
mySimplify relnums = ...
cprimes' relnums = ...
现在这可以按预期工作了。但是,它会将cprimestable
函数暴露给导入此模块的任何内容,这不是我想要的。它是一个内部实现,并不打算被外界称呼。这就是为什么我首先尝试将它放在where
块中。
所以最后,我结合使用了第二种方法,明确地说明了我模块的导出。它是这样的:
module PrimeStuff ( cprimes,
...
)
where
...
cprimes :: [Integer] -> [Integer]
cprimes relnums = cprimetables (mySimplify relnums)
cprimetables = (Memo.list Memo.integral) cprimes'
where
mySimplify relnums = ...
cprimes' relnums = ...
这样,似乎cprimestable
中的memoized结果不会过早收集垃圾。它还隐藏了这个实现,因此导入该模块的任何东西都只知道函数cprimes
,该函数将整数列表作为参数。
来自stackoverflow.com的有用资源,了解如何执行此操作,this用于了解有关记忆的信息,this用于了解有关实施隐藏的信息。