我刚刚开始使用Haskell,我已阅读了LYAH的定义数据类型部分,并尝试实现信念传播的Sum-Product算法。其中一项基本任务是定义概率图形模型。
如下图所示,我试图通过打结来创建图形来表示图形,其中每个节点代表高斯分布并且具有恒定的权重链接(现在)到它的邻居。但是,在尝试定义Mean和Covariance类型时,我在指定Matrix和Vector类型的类型时遇到了一些困难,即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]
在这个简单的例子中,将Mean定义为Double和Covariance类型的Vector作为Double类型的矩阵的语法是什么。另外,如何推广Mean
和Covariance
可以是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.
我正在使用h {here
所述的hmatrix包答案 0 :(得分:2)
Vector
和Matrix
在标量类型上进行参数化(因此您不仅可以使用浮点数“实数”矩阵,还可以使用整数矩阵,复数等矩阵)。这就是GHC通过‘Vector’ has kind ‘* -> *’
告诉您的内容:Vector
本身不是一种类型(类型有种*
,又名Type
)。而是{em>类型函数将类型*
的类型映射到类型*
的类型。像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-category
库还没有优化)。
然后,您还可以在向量空间中参数化其他类型:
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
标记并为边缘保留单独的结构。