Here's a function I wrote in PureScript. It compiles with no errors or warnings. The function does some setting up to handle mouse movement:
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
and velocityRef
are STRef
variables that reference mutable variables. They are being passed in by a calling function.
And here's the compiled JavaScript version of the same code snippet:
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)();
};
};
};
This is the problem I'm facing: The point of this snippet is to call the rotateCube
function with the newly calculated angle obtained from the mouse movement and stored in newAngle
.
However, when I run this code in the browser, it doesn't do what I want it to do. I then tried debugging the JavaScript code and I discovered that the newAngle
variable ends up having the value of
{ x: NaN, y: NaN }
After tracing the code I found out the reason was because the variable v5.x
(which is angle.x
in PureScript) has a value that is of Number
type, but the variables v2
and v4.x
(x
and lastPos.x
) have the following type
v2: Object[1]
0: 127
length: 1
instead of being a Number
. The same thing happens in the case of y
and lastPos.y
. I'm guessing the addition of this with the Number
type of angle.x
results in NaN
. But why is that happening? Why aren't x
and lastPos.x
turning out to be Number
s at runtime in javascript and instead look like these arrays?
I'm not sure if this is a clue or not, but the on
function in Control.Monad.Eff.JQuery
takes a function as an argument (in this case, moveHandler
) that will be executed when the event occurs and that function should be of type
(JQueryEvent -> JQuery -> Eff (dom :: DOM | eff) a))
But inside moveHandler
I have two side effects, one is DOM
and the other is ST
because of using readSTRef
.
I actually tried explicitly declaring the type for moveHandler
before it's definition like this
moveHandler :: forall e h. JQueryEvent -> JQuery -> Eff (dom :: DOM, st :: ST h | eff) Unit))
But this would always give me a Could not match type
error, which is why I ended up just not mentioning an explicit type for moveHandler
. Could this be a reason why the code isn't working? Is it not possible to have an ST
effect also happening in the event handler callback function?
getPageX
is wrong inpurescript-jquery
. – Phil Freemanx
andy
that have the problem. EvenlastPos.x
andlastPos.y
end being an array instead ofNumber
type, but they get their values from thereadSTRef
function. Also worth mentioning, I have another fuction in my program that also usesreadSTRef
but over there the value is assigned normally so I'm really confused as to why this is happening only insidemoveHandler
– George V.M.getPageX
returns jQuery instance instead of a Number – Yury Tarabanko