【问题标题】:How can I create a recursively typed graph(a graph of graph)?如何创建递归类型图(图的图)?
【发布时间】:2013-09-26 23:00:32
【问题描述】:

我想创建一个图形结构,它也可以用来表示更高级别的图形。我认为这个问题最好通过一个图来表达:

您可能已经注意到,n-1 级别的图表包含 n 级别的节点。没有混合图,即图中的所有节点都具有相同的级别。

我的用例的另一个方面是节点基本上只是一个函数。因此,1 级图是函数的互连(想想神经网络)。

我还需要图的连接矩阵是一个独立的对象,而不是节点的属性(即我需要一些对象来表示所有的连接,而不是Node.Next作为每个节点的属性)。

我想到的一种伪代码方法是:

class Node<T>:
    func :: T -> T //The function 'func' takes a value of type 'T' and returns another value of type 'T'.

class Network<T where T is instance of Node> inherits Node<T2>:
    ConnectionMatrix<T> matrix;
    override/implement func :: T2 -> T2;

//I'm applying some sort of pattern matching on types here:
type ConnectionMatrix<Network<T>> = 
    Dictionary<Nerwork<T>, Dictionary<Nerwork<T>, ConnectionMatrix<T>>>
type ConnectionMatrix<Node> = Dictionary<Node, Dictionary<Node, Integer>>

但正如您所见,它是不完整的,目前无法用我知道的任何语言来表示。

只要不是动态类型,实现语言应该不是问题。

编辑: 以下解决方案(如答案中所建议)不适用于我的设计:

data Connection = Connection {
    weight :: Double,
    length :: Int
} deriving (Eq, Show)

data Graph a = Graph {
    nodes :: M.Map Int a,
    edges :: M.Map (Int, Int) Connection
} deriving (Eq, Show)

data Network a = Simple a | Nested (Network (Graph a))
    deriving (Eq, Show)

原因是我需要一个加权图:

  • 两个0级图(即简单节点)之间的连接与上面定义的Connection类型相同。
  • 两个级别 1 图形之间的连接将是 M.Map (Int, Int) Connection 类型,因此图形的边应该是 M.Map (Int, Int) (M.Map (Int, Int) Connection) 类型。这意味着 1 级图中的每条边都会返回 0 级图的内部节点之间的一组连接。
  • 同样,对于第 n 级图,连接类型应为 M.Map (Int, Int) &lt;Type of connection for Level n-1 graph&gt;

编辑:其实上面的表述对我有用;我只需要以简化的形式存储边缘。但是有没有可能写出满足上述条件的程序呢?

【问题讨论】:

    标签: java c#-4.0 haskell language-agnostic static-typing


    【解决方案1】:

    您可以将图形的节点表示为具有唯一标签和值的事物。这样,值可以是任意的(函数),没有任何约束,并且标签用于标识节点。然后您可以将图形表示为两个映射:一个将节点标签映射到它们的值,另一个将节点标签映射到相邻节点。

    import qualified Data.Set as S
    import qualified Data.Map as M
    
    data Graph l a = Graph
        { nodes :: M.Map l a
        , edges :: M.Map l (S.Set l)
        }
    

    如果您想要具有类型静态深度的网络,您可以只定义

    type Graph0 l a = a
    type Graph1 l a = Graph l a
    type Graph2 l a = Graph l (Graph l a)
    -- etc
    

    如果你想拥有可变深度的网络(我认为这是你想要的),你可以定义一个递归数据类型,其中递归是非均匀的,比如

    data Network l a = Level0 a | LevelUp (Network l (Graph l a))
    

    然后Network 类型的每个值都包含一个与其包含的Network 构造函数数量相同级别的图形,这是由类型系统强制执行的。例如,可以使用

    构造一个 2 级图
    LevelUp . LevelUp . Level0 :: Graph l (Graph l a) -> Network l a
    

    【讨论】:

    • 嘿,我刚刚编辑了我的问题以说明此解决方案不起作用的原因。但是,我必须说我对 Network 类型的简洁性感到惊讶。我花了 3 个小时才弄清楚到底发生了什么(我对 Haskell 的 Map 和 Set 数据类型缺乏了解并没有帮助)。
    猜你喜欢
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 2018-02-17
    相关资源
    最近更新 更多