Haskell 某些变量名无法编译代码
Haskell code won't compile with certain variable names
我从 GHCi 收到一个我无法解释的错误。我正在使用以下代码(其中绝大多数似乎与问题无关,但我无法用更少的代码复制问题;注释掉的行是我想添加以替换虚拟行的行in 0
行)
import Linear
apply x f = f x
pos xs = -- smallest i where xs!!i > 0, else length xs
let aux xs n = case xs of
x:t -> if x > 0 then n
else aux t (n+1)
[] -> n
in aux xs 0
optimize d opt d_opt funs d_funs x0 p0 eps =
let n = length funs in
let aux x p f_best = let feas = map (apply x) funs in
let i = pos feas in
let (g,a,f_best) =
if i == n then
let g = d_opt x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g / (sqrt prod) in
let f_best = min (opt x) f_best in
let a = (opt x - f_best) / (sqrt prod) in
(g,a,f_best)
else
let g = (d_funs!!i) x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g / (sqrt prod) in
let a = ((funs!!i) x) / (sqrt prod) in
(g,a,f_best)
in
let b = (1+d*a)/(d+1) in
let b' = 2/(1+a) in
let b'' = (1-a^2)*(d^2)/(d^2-1) in
let h = p !* g in
let y = x - b*g in
-- let q = (p - g'*(transpose g')*b*b')*b'' in
-- aux y q f_best
0
-- in aux x0 p0 (1/0)
in 0
此代码导致 GHCi 抛出六个错误,包括突出显示 let h = p !* g in
中的 p
;但是,当我将该行更改为 let g = p !* g in
时,它会通过。不幸的是,这样做然后取消注释下一行 (let x = x - b*g in
) 会导致抛出相同的错误(包括在同一位置突出显示 p
)。
p
和 p0
应该是使用 Linear 包的 (n×n) 方阵,而 g
、x
和 x0
应该是 (n-by-1) 向量; d
是整数,opt
是n-space上的线性函数,funs
是n-space上的凸函数列表,d_opt
和d_funs
是各自的梯度,eps
是真实的。
如果您能提供任何有助于编译的帮助,我们将不胜感激。谢谢!
编辑:这是错误消息之一。 let g = d_opt x
、let f_best = min (opt x) f_best
、let g = (d_funs!!i) x
、let a = ((funs!!i) x) / (sqrt prod)
、let b = (1+d*a)/(d+1)
、
也有类似的
Lenstra.hs:57:34: error:
• Occurs check: cannot construct the infinite type: a1 ~ m a1
Expected type: m (m a1)
Actual type: m (m (m a1))
• In the first argument of ‘(!*)’, namely ‘p’
In the expression: p !* g
In an equation for ‘h’: h = p !* g
• Relevant bindings include
h :: m a1 (bound at Lenstra.hs:57:30)
b'' :: m a1 (bound at Lenstra.hs:56:30)
b' :: m a1 (bound at Lenstra.hs:55:30)
b :: m a1 (bound at Lenstra.hs:54:30)
g :: m a1 (bound at Lenstra.hs:37:31)
a :: m a1 (bound at Lenstra.hs:37:33)
aux :: m a1 -> m (m (m a1)) -> p8 -> p9 (bound at Lenstra.hs:35:9)
(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
|
57 | let h = p !* g in
| ^
Failed, no modules loaded.
有几个错误:
- 其中整数
d
用作浮点数,需要使用fromIntegral
,例如:b = (1 + fromIntegral d * a)/(fromIntegral d + 1)
- 向量和矩阵的标量multiplication/division不能使用
*
和/
。您必须对向量使用 *^
、^*
和 ^/
运算符,对矩阵使用 !!*
和 !!/
。
- 向量和矩阵的逐点和与差不能使用
+
和-
。您必须对向量使用 ^+^
和 ^-^
,对矩阵使用 !+!
和 !-!
。
- 对于向量
g'
,transpose g'
不起作用,因此 g' * transpose g'
没有祈祷。使用 outer g' g'
获取由 g'
作为列向量与 g'
作为行向量的乘积得到的矩阵,如果这就是你想要做的。
- 在定义
q
的范围内没有 g'
。也许您想从 if
语句中 return g'
?
let g = some expression with g
不会起作用,因为您将创建一个永远循环的递归定义。您将需要使用一个新变量——您在某些地方正确地做到了这一点,但在其他地方却不正确。
还有一个严重的逻辑错误,至少在你的注释语句未被注释的版本中。函数 aux
除了对 aux
的尾调用之外,从 return 不会做任何事情,因此它必然会永远循环。我什至不知道它应该是什么类型return。您需要一些停止条件(可能 returning f_best
或其他)。
您会发现将类型签名添加到 optimize
及其 aux
函数有助于控制这些错误。以下type-checks但仍然包含几个错误(无限循环等):
import Linear
import Data.Vector (Vector)
apply x f = f x
pos :: (Ord a, Num a) => [a] -> Int
pos xs = -- smallest i where xs!!i > 0, else length xs
let aux xs n = case xs of
x:t -> if x > 0 then n
else aux t (n+1)
[] -> n
in aux xs 0
type Matrix a = Vector (Vector a)
optimize
:: Integer
-> (Vector Double -> Double)
-> (Vector Double -> Vector Double)
-> [Vector Double -> Double]
-> [Vector Double -> Vector Double]
-> Vector Double
-> Matrix Double
-> Double
-> a
optimize d opt d_opt funs d_funs x0 p0 eps =
let n = length funs in
let aux
:: Vector Double
-> Matrix Double
-> Double
-> a
aux x p f_best = let feas = map (apply x) funs in
let i = pos feas in
let g :: Vector Double
(g,g',a,f_best) =
if i == n then
let g = d_opt x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g ^/ (sqrt prod) in -- **LOOP**
let f_best = min (opt x) f_best in
let a = (opt x - f_best) / (sqrt prod) in
(g,g',a,f_best)
else
let g = (d_funs!!i) x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g ^/ (sqrt prod) in -- **LOOP**
let a = ((funs!!i) x) / (sqrt prod) in
(g,g',a,f_best)
in
let b = (1+fromIntegral d*a)/(fromIntegral d+1) in
let b' = 2/(1+a) in
let b'' = (1-a^2)*(fromIntegral d^2)/(fromIntegral d^2-1) in
let h = p !* g in
let y = x ^-^ b*^g in
let q = (p !-! outer g' g' !!* (b*b')) !!* b'' in
aux y q f_best
in aux x0 p0 (1/0)
最后,当你得到这个 运行 时,你可能想将它连同对算法的解释和一些 运行 示例一起提交给 Code Review Stack Exchange。我认为有很多风格上的改进可以使它更加地道。
我从 GHCi 收到一个我无法解释的错误。我正在使用以下代码(其中绝大多数似乎与问题无关,但我无法用更少的代码复制问题;注释掉的行是我想添加以替换虚拟行的行in 0
行)
import Linear
apply x f = f x
pos xs = -- smallest i where xs!!i > 0, else length xs
let aux xs n = case xs of
x:t -> if x > 0 then n
else aux t (n+1)
[] -> n
in aux xs 0
optimize d opt d_opt funs d_funs x0 p0 eps =
let n = length funs in
let aux x p f_best = let feas = map (apply x) funs in
let i = pos feas in
let (g,a,f_best) =
if i == n then
let g = d_opt x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g / (sqrt prod) in
let f_best = min (opt x) f_best in
let a = (opt x - f_best) / (sqrt prod) in
(g,a,f_best)
else
let g = (d_funs!!i) x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g / (sqrt prod) in
let a = ((funs!!i) x) / (sqrt prod) in
(g,a,f_best)
in
let b = (1+d*a)/(d+1) in
let b' = 2/(1+a) in
let b'' = (1-a^2)*(d^2)/(d^2-1) in
let h = p !* g in
let y = x - b*g in
-- let q = (p - g'*(transpose g')*b*b')*b'' in
-- aux y q f_best
0
-- in aux x0 p0 (1/0)
in 0
此代码导致 GHCi 抛出六个错误,包括突出显示 let h = p !* g in
中的 p
;但是,当我将该行更改为 let g = p !* g in
时,它会通过。不幸的是,这样做然后取消注释下一行 (let x = x - b*g in
) 会导致抛出相同的错误(包括在同一位置突出显示 p
)。
p
和 p0
应该是使用 Linear 包的 (n×n) 方阵,而 g
、x
和 x0
应该是 (n-by-1) 向量; d
是整数,opt
是n-space上的线性函数,funs
是n-space上的凸函数列表,d_opt
和d_funs
是各自的梯度,eps
是真实的。
如果您能提供任何有助于编译的帮助,我们将不胜感激。谢谢!
编辑:这是错误消息之一。 let g = d_opt x
、let f_best = min (opt x) f_best
、let g = (d_funs!!i) x
、let a = ((funs!!i) x) / (sqrt prod)
、let b = (1+d*a)/(d+1)
、
Lenstra.hs:57:34: error:
• Occurs check: cannot construct the infinite type: a1 ~ m a1
Expected type: m (m a1)
Actual type: m (m (m a1))
• In the first argument of ‘(!*)’, namely ‘p’
In the expression: p !* g
In an equation for ‘h’: h = p !* g
• Relevant bindings include
h :: m a1 (bound at Lenstra.hs:57:30)
b'' :: m a1 (bound at Lenstra.hs:56:30)
b' :: m a1 (bound at Lenstra.hs:55:30)
b :: m a1 (bound at Lenstra.hs:54:30)
g :: m a1 (bound at Lenstra.hs:37:31)
a :: m a1 (bound at Lenstra.hs:37:33)
aux :: m a1 -> m (m (m a1)) -> p8 -> p9 (bound at Lenstra.hs:35:9)
(Some bindings suppressed; use -fmax-relevant-binds=N or -fno-max-relevant-binds)
|
57 | let h = p !* g in
| ^
Failed, no modules loaded.
有几个错误:
- 其中整数
d
用作浮点数,需要使用fromIntegral
,例如:b = (1 + fromIntegral d * a)/(fromIntegral d + 1)
- 向量和矩阵的标量multiplication/division不能使用
*
和/
。您必须对向量使用*^
、^*
和^/
运算符,对矩阵使用!!*
和!!/
。 - 向量和矩阵的逐点和与差不能使用
+
和-
。您必须对向量使用^+^
和^-^
,对矩阵使用!+!
和!-!
。 - 对于向量
g'
,transpose g'
不起作用,因此g' * transpose g'
没有祈祷。使用outer g' g'
获取由g'
作为列向量与g'
作为行向量的乘积得到的矩阵,如果这就是你想要做的。 - 在定义
q
的范围内没有g'
。也许您想从if
语句中 returng'
? let g = some expression with g
不会起作用,因为您将创建一个永远循环的递归定义。您将需要使用一个新变量——您在某些地方正确地做到了这一点,但在其他地方却不正确。
还有一个严重的逻辑错误,至少在你的注释语句未被注释的版本中。函数 aux
除了对 aux
的尾调用之外,从 return 不会做任何事情,因此它必然会永远循环。我什至不知道它应该是什么类型return。您需要一些停止条件(可能 returning f_best
或其他)。
您会发现将类型签名添加到 optimize
及其 aux
函数有助于控制这些错误。以下type-checks但仍然包含几个错误(无限循环等):
import Linear
import Data.Vector (Vector)
apply x f = f x
pos :: (Ord a, Num a) => [a] -> Int
pos xs = -- smallest i where xs!!i > 0, else length xs
let aux xs n = case xs of
x:t -> if x > 0 then n
else aux t (n+1)
[] -> n
in aux xs 0
type Matrix a = Vector (Vector a)
optimize
:: Integer
-> (Vector Double -> Double)
-> (Vector Double -> Vector Double)
-> [Vector Double -> Double]
-> [Vector Double -> Vector Double]
-> Vector Double
-> Matrix Double
-> Double
-> a
optimize d opt d_opt funs d_funs x0 p0 eps =
let n = length funs in
let aux
:: Vector Double
-> Matrix Double
-> Double
-> a
aux x p f_best = let feas = map (apply x) funs in
let i = pos feas in
let g :: Vector Double
(g,g',a,f_best) =
if i == n then
let g = d_opt x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g ^/ (sqrt prod) in -- **LOOP**
let f_best = min (opt x) f_best in
let a = (opt x - f_best) / (sqrt prod) in
(g,g',a,f_best)
else
let g = (d_funs!!i) x in
let g' = p !* g in
let prod = g `dot` g' in
let g = g ^/ (sqrt prod) in -- **LOOP**
let a = ((funs!!i) x) / (sqrt prod) in
(g,g',a,f_best)
in
let b = (1+fromIntegral d*a)/(fromIntegral d+1) in
let b' = 2/(1+a) in
let b'' = (1-a^2)*(fromIntegral d^2)/(fromIntegral d^2-1) in
let h = p !* g in
let y = x ^-^ b*^g in
let q = (p !-! outer g' g' !!* (b*b')) !!* b'' in
aux y q f_best
in aux x0 p0 (1/0)
最后,当你得到这个 运行 时,你可能想将它连同对算法的解释和一些 运行 示例一起提交给 Code Review Stack Exchange。我认为有很多风格上的改进可以使它更加地道。