hmatrix向量和矩阵的Haskell数据类型

hmatrix向量和矩阵的Haskell数据类型,haskell,graph,functional-programming,ghci,Haskell,Graph,Functional Programming,Ghci,我刚从Haskell开始,我已经阅读了LYAH的定义数据类型部分,并试图实现信念传播的和积算法。基本任务之一是定义概率图形模型 如下图所示,我试图通过打结来创建一个图,其中每个节点表示高斯分布,并且(目前)与它的邻居有恒定的权重链接。然而,当试图定义均值和协方差类型时,我在指定矩阵和向量类型时遇到了一些困难,即Float或Double module Graph(Graph) where import Numeric.LinearAlgebra data Mean = Mean Vector

我刚从Haskell开始,我已经阅读了LYAH的定义数据类型部分,并试图实现信念传播的和积算法。基本任务之一是定义概率图形模型

如下图所示,我试图通过打结来创建一个图,其中每个节点表示高斯分布,并且(目前)与它的邻居有恒定的权重链接。然而,当试图定义均值和协方差类型时,我在指定矩阵和向量类型时遇到了一些困难,即Float或Double

module Graph(Graph) where

import Numeric.LinearAlgebra

data Mean = Mean Vector
data Covariance = Covariance Matrix
data Gaussian = Gaussian Mean Covariance

data Node = Node [Node] Gaussian
data Graph = Graph [Node]
在这个简单的示例中,将均值定义为Double类型的向量,将协方差定义为Double类型的矩阵的语法是什么。此外,如何将
平均值
协方差
归纳为Float或Double类型

我目前从GHCi获得以下信息

Graph.hs:5:18: error:
    • Expecting one more argument to ‘Vector’
      Expected a type, but ‘Vector’ has kind ‘* -> *’
    • In the type ‘Vector’
      In the definition of data constructor ‘Mean’
      In the data declaration for ‘Mean’
Failed, modules loaded: none.

我正在使用hmatrix包,如所述,
向量
矩阵
都是在标量类型上参数化的(因此不仅可以有浮点“实数”矩阵,还可以有整数、复数等矩阵)。这是GHC通过
'Vector'具有种类'*->*'
告诉您的:就其本身而言,
Vector
不是一种类型(类型具有种类
*
,又称
类型
)。相反,它是一种类型函数,将种类的类型映射到种类的类型。像
Double
这样的标量已经是普通类型了,所以您可以对它们应用
Vector

GHCi> :kind Vector
Vector :: * -> *
GHCi> :k Double
Double :: *
GHCi> :k Vector Double
Vector Double :: *
因此你需要

newtype Mean = Mean (Vector Double)
newtype Covariance = Covariance (Matrix Double)
newtype
与这里的
data
做的事情相同,但效率更高,因为不需要额外的框/指针)

或者,您可以使用更有意义的类型化向量空间,例如

import Math.LinearMap.Category

newtype Mean v = Mean v
newtype Covariance v = Covariance (v +> DualVector v)
这样做的好处是在编译时检查维度,这可以防止严重的运行时错误(原则上也可以提高性能,不过坦率地说,
linearmap类别
库还没有得到优化)

然后还可以参数化向量空间上的其他类型:

data Gaußian v = Gaußian (Mean v) (Covariance v)
data Node v = Node [Node v] (Gaussian v)
data Graph v = Graph [Node v]

与您的问题有些无关:这种打结方式感觉确实很优雅,但它并不适合表示图形,因为节点无法进行身份检查。对于所有可区分的方法,图中的任何循环都会导致一个无限结构。实际上,你不会随便给你的节点贴标签,比如
Int
标签,并为边缘保留一个单独的结构。

这是一个多么奇妙的答案;非常感谢。这为我澄清了一些事情。我确实对打结和无意中创造一个无限结构有些怀疑。另一种方式(保持邻接矩阵等)似乎并不雅观。