Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中从功能上处理依赖项解析_Haskell_Design Patterns_Dependencies_Spreadsheet - Fatal编程技术网

在Haskell中从功能上处理依赖项解析

在Haskell中从功能上处理依赖项解析,haskell,design-patterns,dependencies,spreadsheet,Haskell,Design Patterns,Dependencies,Spreadsheet,我正在Haskell中实现类似于电子表格引擎的东西 有ETables,它们有一行单元格,其中包含AST形式的表达式(例如BinOp+2),可以包含对ETables的其他单元格的引用 主功能应将这些etable转换为VTables,其中包含单元格中的完全解析值(例如,单元格BinOp+2应解析为IntValue 4)。当单元格没有外部引用时,这非常容易,因为您可以从单元格的表达式AST(例如,eval(BinOpExpr op l r)=IntValue$(eval l)op(eval r),减去

我正在Haskell中实现类似于电子表格引擎的东西

ETables
,它们有一行单元格,其中包含AST形式的表达式(例如
BinOp+2
),可以包含对
ETables
的其他单元格的引用

主功能应将这些
etable
转换为
VTables
,其中包含单元格中的完全解析值(例如,单元格
BinOp+2
应解析为
IntValue 4
)。当单元格没有外部引用时,这非常容易,因为您可以从单元格的表达式AST(例如,
eval(BinOpExpr op l r)=IntValue$(eval l)op(eval r)
,减去取消装箱和类型检查)自下而上构建值,一直到表(
evalTable=(map.map)eval行

然而,我想不出一个“自然”的方式来处理这个问题,当外部引用被抛出到混合中时。假设我不能对引用的单元格调用
eval
并使用其值,因为Haskell不够聪明,无法缓存结果并在独立计算该单元格时重新使用它,这对吗


我想到的最好的方法是使用一个逐步填充的
状态[VTable]
,因此缓存是显式的(每个eval调用在返回之前用返回值更新状态)。这应该行得通,但感觉“程序性的”。有没有一种更惯用的方法是我所缺少的?

哈斯克尔默认情况下不会进行记忆化,因为这通常会占用太多内存,所以你不能仅仅依靠
eval
做正确的事情。然而,惰性评估的本质意味着数据结构在某种意义上是记忆化的:大型惰性结构中的每个thunk只评估一次。这意味着您可以通过在内部定义一个大的惰性数据结构并用对该结构的访问替换递归调用来记忆函数。该结构的每个部分最多只计算一次

我认为对电子表格建模的最优雅的方法是一个大的、懒惰的有向图,其中单元格作为节点,引用作为边。然后您需要以递归的方式定义
VTable
图形,这样所有的递归都会通过图形本身,这将以我上面描述的方式记忆结果

有两种简便的方法可以为图形建模。一种选择是使用带有整数的显式映射作为节点标识符,或者甚至可以使用某种数组。另一种选择是使用现有的图形库;这将为您节省一些工作,并确保您有一个很好的图形抽象,但需要一些前期工作才能理解。我非常喜欢“函数图库”,但要理解它确实需要一点前期阅读和思考。性能不会有很大的不同,因为它也是按照
IntMap
实现的


我吹响了自己的号角,写了几篇关于这个答案的博文:一篇关于(带图片!),另一篇关于。我相信,把这两个想法放在一起会让你得到你想要的。

Haskell默认情况下不会进行记忆,因为这通常会占用太多内存,所以你不能仅仅依靠
eval
做正确的事情。然而,惰性评估的本质意味着数据结构在某种意义上是记忆化的:大型惰性结构中的每个thunk只评估一次。这意味着您可以通过在内部定义一个大的惰性数据结构并用对该结构的访问替换递归调用来记忆函数。该结构的每个部分最多只计算一次

我认为对电子表格建模的最优雅的方法是一个大的、懒惰的有向图,其中单元格作为节点,引用作为边。然后您需要以递归的方式定义
VTable
图形,这样所有的递归都会通过图形本身,这将以我上面描述的方式记忆结果

有两种简便的方法可以为图形建模。一种选择是使用带有整数的显式映射作为节点标识符,或者甚至可以使用某种数组。另一种选择是使用现有的图形库;这将为您节省一些工作,并确保您有一个很好的图形抽象,但需要一些前期工作才能理解。我非常喜欢“函数图库”,但要理解它确实需要一点前期阅读和思考。性能不会有很大的不同,因为它也是按照
IntMap
实现的


我吹响了自己的号角,写了几篇关于这个答案的博文:一篇关于(带图片!),另一篇关于。我相信,把这两个想法放在一起应该会得到你想要的。

你所说的“外部引用”是什么意思?单元格之外的引用(以及自下而上的数据流之外的引用)。假设excel等价物为=A1+2,其中A1是另一个带数字的单元格,如果要计算该单元格,则需要先计算该单元格。当单元格递归引用彼此时,它会变得有趣;)是的,我已经检测到了循环,但我认为我不会处理固定点。我将
VTable
单元格标记为“评估”,以便动态检测循环(我有一个静态构造的依赖关系图,当前用于在表更改时对
VTable
单元格进行不验证,但我也可以用于此目的)您所说的“外部引用”是什么意思?单元格外部的引用(并且在自下而上的数据流之外)。想象excel等价物为=A1+2,其中A1是另一个带数字的单元格,如果要计算该单元格,则需要先计算该单元格。当单元格递归地相互引用时,它会变得有趣;)是的,我是