【发布时间】:2017-06-26 18:00:33
【问题描述】:
这是我用 PureScript 编写的一个函数。它编译时没有错误或警告。该函数进行了一些设置以处理鼠标移动:
startMouseHandlers :: forall h e. STRef h {x::Number, y::Number}
-> STRef h {x::Number, y::Number}
-> Eff (dom :: DOM, st :: ST h | e) Unit
startMouseHandlers angleRef velocityRef = do
lastMousePos <- newSTRef {x: 0.0, y: 0.0}
body <- JQuery.body
let
moveHandler event jq = do
x <- getPageX event
y <- getPageY event
lastPos <- readSTRef lastMousePos
angle <- readSTRef angleRef
let newAngle = {
x: angle.x + x - lastPos.x,
y: angle.y + y - lastPos.y
}
rotateCube angleRef newAngle
void $ writeSTRef lastMousePos {x: x, y: y}
on "mousemove" movehandler body
angleRef 和velocityRef 是引用可变变量的STRef 变量。它们是由调用函数传入的。
这是相同代码 sn-p 的编译 JavaScript 版本:
var startMouseHandlers = function (angleRef) {
return function (velocityRef) {
return function __do() {
var v = Control_Monad_ST.newSTRef({
x: 0.0,
y: 0.0
})();
var v1 = Control_Monad_Eff_JQuery.body();
var moveHandler = function (event) {
return function (jq) {
return function __do() {
var v2 = Control_Monad_Eff_JQuery.getPageX(event)();
var v3 = Control_Monad_Eff_JQuery.getPageY(event)();
var v4 = Control_Monad_ST.readSTRef(v)();
var v5 = Control_Monad_ST.readSTRef(angleRef)();
var newAngle = {
x: (v5.x + v2) - v4.x,
y: (v5.y + v3) - v4.y
};
rotateCube(angleRef)(newAngle)();
return Data_Functor["void"](Control_Monad_Eff.functorEff)(Control_Monad_ST.writeSTRef(v)({
x: v2,
y: v3
}))();
};
};
};
return Control_Monad_Eff_JQuery.on("mousemove")(moveHandler)(v1)();
};
};
};
这是我面临的问题:这个sn-p的重点是调用rotateCube函数,从鼠标移动中获得新计算的角度并存储在newAngle中。
但是,当我在浏览器中运行此代码时,它并没有做我想要它做的事情。然后我尝试调试 JavaScript 代码,我发现 newAngle 变量最终的值为
{ x: NaN, y: NaN }
跟踪代码后我发现原因是因为变量v5.x(在PureScript中是angle.x)的值是Number类型,但是变量@ 987654334@和v4.x(x和lastPos.x)有以下类型
v2: Object[1]
0: 127
length: 1
而不是Number。同样的事情发生在y 和lastPos.y 的情况下。我猜想加上Number 类型的angle.x 会导致NaN。但为什么会这样?为什么 x 和 lastPos.x 在运行时在 javascript 中不是 Numbers 而是看起来像这些数组?
我不确定这是否是一个线索,但Control.Monad.Eff.JQuery 中的on 函数将一个函数作为参数(在本例中为moveHandler),该函数将在事件发生时执行并且该函数应该是类型
(JQueryEvent -> JQuery -> Eff (dom :: DOM | eff) a))
但是在moveHandler里面我有两个副作用,一个是DOM,一个是ST,因为使用了readSTRef。
我实际上尝试在像这样定义之前明确声明 moveHandler 的类型
moveHandler :: forall e h. JQueryEvent -> JQuery -> Eff (dom :: DOM, st :: ST h | eff) Unit))
但这总是会给我一个Could not match type 错误,这就是为什么我最终没有提到moveHandler 的显式类型。这可能是代码不起作用的原因吗?是不是不可能在事件处理回调函数中也出现ST的效果?
【问题讨论】:
-
有可能是
getPageX的类型在purescript-jquery中有错误。 -
但问题不只是
x和y。即使lastPos.x和lastPos.y最终是一个数组而不是Number类型,但它们从readSTRef函数中获取它们的值。另外值得一提的是,我的程序中有另一个函数也使用readSTRef,但那里的值是正常分配的,所以我真的很困惑为什么这只发生在moveHandler内 -
getPageX返回 jQuery 实例而不是数字 -
我能做些什么来解决这个问题吗?
-
@GeorgeV.M.修复问题的拉取请求? :)
标签: jquery functional-programming purescript