【发布时间】:2017-04-01 12:16:31
【问题描述】:
我想使用 GADT 在 Haskell 中实现张量演算的类型安全,所以规则是:
- 张量是具有“楼上”或“楼下”指标的 n 维度量,例如: - 是没有指标的张量(标量), 是具有一个“楼上”索引的张量, 是一个带有一堆“楼上”和“楼下”不雅点的张量
-
您可以添加相同类型的张量,这意味着它们具有相同的 indecies 签名。第一个张量的第 0 个索引与第二个张量的第 0 个索引的类型相同(楼上或楼下),依此类推...
所以我希望 Haskell 的类型检查器不允许我编写不遵循这些规则的代码,否则它不会编译。
这是我使用 GADT 的尝试:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeOperators #-}
data Direction = T | X | Y | Z
data Index = Zero | Up Index | Down Index deriving (Eq, Show)
plus :: Index -> Index -> Index
plus Zero x = x
plus (Up x) y = Up (plus x y)
plus (Down x) y = Down (plus x y)
data Tensor a = (a ~ Zero) => Scalar Double |
forall b. (a ~ Up b) => Cov (Direction -> Tensor b) |
forall b. (a ~ Down b) => Con (Direction -> Tensor b)
add :: Tensor a -> Tensor a -> Tensor a
add (Scalar x) (Scalar y) = (Scalar (x + y))
add (Cov f) (Cov g) = (Cov (\d -> add (f d) (g d)))
add (Con f) (Con g) = (Con (\d -> add (f d) (g d)))
mul :: Tensor a -> Tensor b -> Tensor (plus a b)
mul (Scalar x) (Scalar y) = (Scalar (x*y))
mul (Scalar x) (Cov f) = (Cov (\d -> mul (Scalar x) (f d)))
mul (Scalar x) (Con f) = (Con (\d -> mul (Scalar x) (f d)))
mul (Cov f) y = (Cov (\d -> mul (f d) y))
mul (Con f) y = (Con (\d -> mul (f d) y))
但我得到了:
Couldn't match type 'Down with `plus ('Down b1)'
Expected type: Tensor (plus a b)
Actual type: Tensor ('Down b)
Relevant bindings include
f :: Direction -> Tensor b1 (bound at main.hs:28:10)
mul :: Tensor a -> Tensor b -> Tensor (plus a b)
(bound at main.hs:24:1)
In the expression: (Con (\ d -> mul (f d) y))
In an equation for `mul':
mul (Con f) y = (Con (\ d -> mul (f d) y))
有什么问题?
【问题讨论】:
-
您将
plus写为(值级别)函数,但您试图在类型中使用它。 Haskell 做不到。 (它认为mul的返回类型中的plus是一个类型参数。)使用类型族。 -
我使用了类型运算符
-
我建议你也考虑a coordinate-free approach to tensors,没有那些愚蠢的索引......
-
@leftaroundabout 哇酷图书馆。不仅仅是一个抽象模型,还有一些主力——反演、特征值、...。谢谢指点!
-
我其实很喜欢索引符号。也许这只是一种偏见,我在这个符号中学习了广义相对论......
标签: haskell type-safety gadt data-kinds