【发布时间】:2020-08-03 16:58:18
【问题描述】:
我从 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×1 ) 向量; d 是整数,opt 是 n 空间上的线性函数,funs 是 n 空间上的凸函数列表,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.
【问题讨论】:
-
这可能意味着
p和q的类型不同。 -
甚至没有阅读问题:
let x = x - b*g定义x本身,而不是您可能想要的一些以前可用的x。为新的x选择一个新名称并相应地修改您的代码。p相同。 95% 相信您的问题会消失。 -
但是这个算法太混乱了,无法有效调试。通常,您将逻辑拆分为执行特定任务的小部分。
let ... in ...链接的数量是巨大的。虽然有 2-3 个let语句并不罕见,但上面的语句看起来并不像 Haskellish。事实上,它看起来也很程序化。 -
@DanielWagner 不幸的是,我尝试将名称更改为
let h = p !* g和let y = x - b*h(保持p的重新定义被注释掉)并且似乎有相同的编译问题 -
@WillemVanOnsem 是的,我希望我有更少的链接,但是替换所有东西会使调试变得更加困难。是否更好?将
if/else的每个分支都粘贴到optimize之外的自己的函数中?