问题描述
我如何将恒定适用表格转化为固定适用表格以阻止它在程序的整个生命周期中保留?我试过这种方法:
- |避免创建CAF的假参数
twoTrues ::() - > [[[Bool]]]
twoTrues _ = map(++(True:repeat False))。 trueBlock< $> [1 ..]
但它似乎不起作用 - 配置文件显示它仍然存在
我发现了一个相关的谷歌搜索结果,给Neil Mitchell,他问了这个问题 - 但该答案指的是一个无效的链接,不幸的是。
泛化。 ,你能概括一下这个变量的函数吗?我的函数在命令 twoTrues
中的命名立即表明这个常量是序列 zeroTrues
中的第三个, oneTrue
, twoTrues
, threeTrues
等等 - 的确如此是。因此,将> twoTrues
概括为一个函数 nTrues
,它接受参数n 并删除 twoTrues
会从程序中删除一个CAF。
zeroTrues
, oneTrue
和 twoTrues
我需要,但是我的程序自然可以扩展为处理 nTrues
,因为 n
> 2 - 所以概括为 nTrues
意味着将一直推广到 zeroTrues
, oneTrue
等等。情况并非总是如此。 注意:可能还有其他CAF需要处理,无论是在代码中,或由GHC的优化产生(在这些病理学案例中并不真正优化)。
然而,这个答案可能涉及程序员的更多工作,而不是严格必要的。 。正如唐的回答所显示的那样,实际上并不需要概括。
另一方面,在某些情况下,概括一个常数可以更清楚地表明你实际上是什么做和帮助可重用性。它甚至可以揭示以更好的系统方式和/或更高效地计算一系列值的方法。关于这种特殊情况(可以忽略) :在这种特殊情况下,我不希望将 nTrues
本身放入无限列表中(这将成为CAF,重新引入原始问题!)而不是一个功能。其中一个原因是,虽然 twoTrues
可能会以无限列表的形式有用,但我无法看到它对我的应用程序是如何有用的(无论如何),对于 nTrues
以无限列表的形式出现。
How do I make a Constant Applicative Form into, well, not a Constant Applicative Form, to stop it being retained for the lifetime of the program?
I've tried this approach:
-- | Dummy parameter to avoid creating a CAF
twoTrues :: () -> [[[Bool]]]
twoTrues _ = map (++ (True : repeat False)) . trueBlock <$> [1..]
but it doesn't seem to work - the profile shows it as still being retained and still marks it as a CAF.
I've found one relevant Google result on this, a reply by Simon Peyton-Jones to Neil Mitchell who asked precisely this question - but that answer refers to a dead link, unfortunately.
Generalise. If you have a constant value, can you generalise this to a function of some variable? The naming of my function in the question, twoTrues
, immediately suggests that this constant is the third in a sequence zeroTrues
, oneTrue
, twoTrues
, threeTrues
etc. - and indeed it is. So generalising twoTrues
into a function nTrues
which takes a parameter n and deleting twoTrues
, would eliminate one CAF from the program.
As it happens, in this case, I had only considered the cases zeroTrues
, oneTrue
and twoTrues
for my program because that was all I needed, but my program could naturally be extended to deal with nTrues
for n
> 2 - so generalising to nTrues
would mean it would make sense to "generalise all the way up" to the users of zeroTrues
, oneTrue
etc. That would not always be the case.
Note: there might still be other CAFs to deal with, either in the code, or produced by GHC's "optimisations" (which are not really optimisations in these pathological cases).
This answer may involve more work by the programmer than is strictly necessary, however. It isn't actually necessary to generalise, as Don's answer shows.
On the other hand, in some cases, generalising a constant can make it more clear what you are actually doing, and aid reusability. It can even reveal ways to compute a series of values in a better systematic way, and/or more efficiently.
A note about this particular case (which can be ignored): In this particular case, I would not want to make nTrues
itself into an infinite list (which would be a CAF again, reintroducing the original problem!) rather than a function. One reason is that while twoTrues
could be useful in the form of an infinite list, I can't see how it would be useful (in my application, anyway) for nTrues
to be in the form of an infinite list.
这篇关于如何在Haskell中创建CAF而不是CAF?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!