我需要数据结构来表示像模型一样的图形。
执行最多的两个操作是:
什么是代表此模型的最佳数据结构?
编辑
我将其用作编译器的一部分。该模型表示计算,其中节点是计算块,而链接是它们之间传递的数据。
我需要从源代码构建此模型。这就是为什么我需要组合操作。我将按语句处理源代码并调整模型,添加新的计算步骤。
我还想通过各种启发式方法“优化”我的计算。这就是为什么我需要用更优化的图替换该图的一部分(优化本身不在问题范围内,但是我需要“替换”操作)。
答案 0 :(得分:1)
实际上,您在这里可以自由地做自己想做的事情:要解决的主要问题是,普通ADT不会给您可变的引用。以下是一些您可能会开始使用的示例。您甚至可能希望使用多个并在它们之间进行转换。
-- Here we have a pair of int indexed maps: the first one associates each
-- vertex index with a vertex value and a list of edge indices, and the
-- second one associates each edge index with an edge value and a pair of
-- vertex indices.
data Graph e v = Graph (M.Map Int (v, [Int])) (M.Map Int (e,Int,Int))
-- Here we use mutable references
newtype Graph s e v = Graph (STRef s (v,[(e,Graph s e v)]))
-- Here we use a single map and assume each vertex value is unique
newtype Graph e v = Graph (M.map v [(e,v)])
-- Single map again: but using ints to distinguish the vertices
newtype Graph e v = Graph (M.map Int (v,[(e,Int)]))
答案 1 :(得分:0)
这是一个间接答案。您问题的模糊性表明您可能是Haskell的新手,如果我认为做错了,请原谅我。
在纯FP中不能很好地使用图形,尤其是与algebraic data types(ADT)可以使用时相比。 ADT是表示抽象语法的常用方法,而反过来又是编译器通常进行操作和优化的方法(直到您开始生成机器代码,然后图形才开始发挥更大作用)。
这是一种非常简单的命令式语言的ADT,可以激发您的胃口:
data Statement
= Assign String Expr
| Print Expr
| If Expr Statement Statement
| Block [Statement]
data Expr
= Variable String
| Add Expr Expr
| Multiply Expr Expr
| Constant Integer
制作语言的常用方法是定义与您的语言功能相对应的这种类型,并围绕该类型组织大部分工作。您使用parser从真实源代码获取该表示形式。
作为Haskell的简介和使用标准工具对编程语言的简单实现,我都听说过关于Write Yourself A Scheme in 48 Hours的美好事情。
除此之外,Implementing Functional Languages: A Tutorial(由GHC的主要负责人Simon Peyton Jones和David Lester撰写)深入探讨了有关实现特定于Haskell的语言的更多细节。它是从1992年开始的,并且语言已经发展了很多,并且从那时起发现了新技术,但是本书仍然应该提供很多指导。
祝你好运!
答案 2 :(得分:0)
使用Haskells模块系统和newtype
构造函数的组合,定义一个newtype
,它包装图形但不从模块导出其构造函数。除了提供构造函数以外,还提供用于构造并使用可强制执行所需不变式的类图结构的方法。看起来像这样:
module SpecialGraph
( SpecialGraph --not e.g. SpecialGraph(..)
, specialGraph) where
import Graph
newtype SpecialGraph = Sg Graph
specialGraph :: Graph -> Maybe SpecialGraph
specialGraph gr = ...
新类型所基于的基础Graph
库可能是在Hackage中找到的几个库之一。我已经使用过fgl
,“功能图库”,并且喜欢它。
在编译器中,您将导入此模块并通过其提供的功能使用SpecialGraph
。
这是解决没有简单的仅ADT表示的问题的标准方法。这里的总体思想是,我们在术语级别(正常的haskell表达式)限制了更通用的数据结构。 fgl
图的实现方式类似,它们是对不同种类Maps
的限制和实用程序,而这些npm run build
又(我认为)是基于对基础树的限制和实用程序。