如何在 Edward Kmett 的 "Linear" 库中使用可变大小向量?
How do I use variable size vectors in Edward Kmett's "Linear" library?
我正在尝试使用 ekmett 的线性库,但我在 Linear.V 中遇到了可变长度向量的一些问题。如何使用 dim
函数获取向量的大小?如何在由嵌套 V
组成的大方阵上使用 trace
?在这两种情况下我都会出错。
最小代码:
import qualified Data.Vector as Vector
import Linear.V (V(V), dim)
import Linear.Vector (outer)
import Linear.Matrix (trace)
v, w :: V n Double -- What do I do here?
v = V $ Vector.fromList [1..5]
w = V $ Vector.fromList [2, 3, 5, 7, 11]
d = dim v
m = outer v w
t = trace m
它给出了这些我不明白的错误:
• Ambiguous type variable ‘n0’ arising from a use of ‘dim’
prevents the constraint ‘(Linear.V.Dim n0)’ from being solved.
Probable fix: use a type annotation to specify what ‘n0’ should be.
These potential instances exist:
two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: dim v
In an equation for ‘d’: d = dim v
• Ambiguous type variable ‘n1’ arising from a use of ‘trace’
prevents the constraint ‘(Linear.V.Dim n1)’ from being solved.
Probable fix: use a type annotation to specify what ‘n1’ should be.
These potential instances exist:
two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: trace m
In an equation for ‘t’: t = trace m
因为 Haskell 不是依赖类型的,它不能将列表的长度提升到类型级别,它可能只在运行时获得。话虽如此,n
的目的是您可以编写在向量大小上具有多态性的代码(例如,您可以确保您没有采用具有不同长度的向量的点积) . 但是如果要使用该信息,您仍然需要在编译时明确指定实际向量的长度。
linear
给你的是 fromVector
,它在运行时执行检查你提供的向量是否匹配你指定的类型。例如,
ghci> :set +t -XDataKinds -XOverloadedLists
ghci> import Linear
ghci> import Linear.V
ghci> fromVector [1,2,3] :: Maybe (V 3 Int)
Just (V {toVector = [1,2,3]})
it :: Maybe (V 3 Int)
ghci> fromVector [1,2,3] :: Maybe (V 2 Int)
Nothing
it :: Maybe (V 3 Int)
因此,在您的情况下,您可能应该执行以下操作:
ghci> Just v = fromVector [1..5] :: Maybe (V 5 Double)
v :: V 5 Double
ghci> Just w = fromVector [2, 3, 5, 7, 11] :: Maybe (V 5 Double)
w :: V 5 Double
ghci> dim v
5
it :: Int
ghci> m = outer v w
m :: V 5 (V 5 Double)
ghci> trace m
<interactive>:44:1: error:
• No instance for (Trace (V 5)) arising from a use of ‘trace’
• In the expression: trace m
In an equation for ‘it’: it = trace m
...annnnd 是的 - 我认为最后一次互动是一个错误(除非有人能看到我遗漏的东西)。 Trace (V 5)
变体应该可以通过 Dim n => Trace (V n)
实例满足,但由于某些原因它不是。
编辑
正如@user2407038 指出的那样,问题是我上面提到的 Dim n => Trace (V n)
不是多元的——它只适用于 n :: *
而我们希望它适用于任何类型(特别是n :: Nat
在这种情况下)。这个限制没有任何理由,所以我们可以继续定义我们自己的实例版本
ghci> :set -XPolyKinds
ghci> instance Dim n => Trace (V n)
ghci> trace m
106.0
我打开了一个issue。
编辑 2
问题现已解决。我认为它可能会出现在 linear
.
的下一个版本中
作为旁注,我使用 -XDataKinds
这样我就可以编写 type-level 文字(它们有种类 GHC.TypeLits.Nat
- 它们是特殊的并且硬连接到 GHC 中)和 -XOverloadedLists
所以我可以写 [1..5] :: Vector Int
.
我正在尝试使用 ekmett 的线性库,但我在 Linear.V 中遇到了可变长度向量的一些问题。如何使用 dim
函数获取向量的大小?如何在由嵌套 V
组成的大方阵上使用 trace
?在这两种情况下我都会出错。
最小代码:
import qualified Data.Vector as Vector
import Linear.V (V(V), dim)
import Linear.Vector (outer)
import Linear.Matrix (trace)
v, w :: V n Double -- What do I do here?
v = V $ Vector.fromList [1..5]
w = V $ Vector.fromList [2, 3, 5, 7, 11]
d = dim v
m = outer v w
t = trace m
它给出了这些我不明白的错误:
• Ambiguous type variable ‘n0’ arising from a use of ‘dim’
prevents the constraint ‘(Linear.V.Dim n0)’ from being solved.
Probable fix: use a type annotation to specify what ‘n0’ should be.
These potential instances exist:
two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: dim v
In an equation for ‘d’: d = dim v
• Ambiguous type variable ‘n1’ arising from a use of ‘trace’
prevents the constraint ‘(Linear.V.Dim n1)’ from being solved.
Probable fix: use a type annotation to specify what ‘n1’ should be.
These potential instances exist:
two instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: trace m
In an equation for ‘t’: t = trace m
因为 Haskell 不是依赖类型的,它不能将列表的长度提升到类型级别,它可能只在运行时获得。话虽如此,n
的目的是您可以编写在向量大小上具有多态性的代码(例如,您可以确保您没有采用具有不同长度的向量的点积) . 但是如果要使用该信息,您仍然需要在编译时明确指定实际向量的长度。
linear
给你的是 fromVector
,它在运行时执行检查你提供的向量是否匹配你指定的类型。例如,
ghci> :set +t -XDataKinds -XOverloadedLists
ghci> import Linear
ghci> import Linear.V
ghci> fromVector [1,2,3] :: Maybe (V 3 Int)
Just (V {toVector = [1,2,3]})
it :: Maybe (V 3 Int)
ghci> fromVector [1,2,3] :: Maybe (V 2 Int)
Nothing
it :: Maybe (V 3 Int)
因此,在您的情况下,您可能应该执行以下操作:
ghci> Just v = fromVector [1..5] :: Maybe (V 5 Double)
v :: V 5 Double
ghci> Just w = fromVector [2, 3, 5, 7, 11] :: Maybe (V 5 Double)
w :: V 5 Double
ghci> dim v
5
it :: Int
ghci> m = outer v w
m :: V 5 (V 5 Double)
ghci> trace m
<interactive>:44:1: error:
• No instance for (Trace (V 5)) arising from a use of ‘trace’
• In the expression: trace m
In an equation for ‘it’: it = trace m
...annnnd 是的 - 我认为最后一次互动是一个错误(除非有人能看到我遗漏的东西)。 Trace (V 5)
变体应该可以通过 Dim n => Trace (V n)
实例满足,但由于某些原因它不是。
编辑
正如@user2407038 指出的那样,问题是我上面提到的 Dim n => Trace (V n)
不是多元的——它只适用于 n :: *
而我们希望它适用于任何类型(特别是n :: Nat
在这种情况下)。这个限制没有任何理由,所以我们可以继续定义我们自己的实例版本
ghci> :set -XPolyKinds
ghci> instance Dim n => Trace (V n)
ghci> trace m
106.0
我打开了一个issue。
编辑 2
问题现已解决。我认为它可能会出现在 linear
.
作为旁注,我使用 -XDataKinds
这样我就可以编写 type-level 文字(它们有种类 GHC.TypeLits.Nat
- 它们是特殊的并且硬连接到 GHC 中)和 -XOverloadedLists
所以我可以写 [1..5] :: Vector Int
.