'Share' or 'cache' an expression parameterized by only ambiguous types?
我有一个棘手的问题;
因此,我知道GHC将"缓存"(由于缺乏更好的术语)顶级定义,并且只计算一次,例如:
即使我在多个位置使用
我想这样做,但是要根据类型级别的上下文进行计算;一个简化的示例是:
1 2 | dependentList :: forall n. (KnownNat n) => [Nat] dependentList = [0..natVal (Proxy @n)] |
所以这里有趣的是,
我的问题是,GHC会认识到它可以共享两个
我的情况稍微复杂一点,但是应该遵循与示例相同的约束条件,但是我的
如果有可能,我完全不反对使用typeclass进行操作; GHC会缓存并重用typeclass词典吗?也许我可以将其烘烤为typeclass dict中的常量以进行缓存?
想法有人吗?还是有人在阅读我的书以了解其工作原理?
我希望这样做的方式是使编译器可以解决该问题,而不是使用手动记忆,但是我愿意接受想法:)
感谢您的时间!
按照@crockeea的建议,我进行了一项实验;这是尝试使用具有多态歧义类型变量的顶级常量,也是一个出于娱乐目的的实际常量,每个常量都包含一个\\'trace \\'
1 2 3 4 5 6 7 8 9 10 11 12 13 |
结果很不幸:
1 2 3 4 5 6 7 8 | λ> main eval: 1 1 eval: 1 1 constant val: 1 1 1 |
因此很明显,它每次使用时都会重新评估多态常数。
但是,如果我们将常量写入类型类(仍然使用歧义类型),则似乎每个实例只能解析一次Dictionary值,当您知道GHC对相同的类实例传递相同的dict时,这是有道理的。当然,它确实为不同的实例重新运行了代码:
1 2 3 4 5 6 7 8 9 10 11 |
结果:
1 2 3 4 5 6 | λ> main dependant class: 1 1 1 dependant class: 2 2 |
就让GHC在编译时执行这些操作而言,您似乎可以使用此技术使用TemplateHaskell的
不幸的是,您不能在typeclass定义中使用它,因为TH会抱怨\\'@ n \\'必须从另一个模块(是TH)中导入,并且在编译时具体未知。您可以在任何使用typeclass值的地方执行此操作,但是它将每次提升一次对其进行求值,因此您必须在任何地方提升它,以获取收益。非常不切实际。