【问题标题】:PureScript functions giving wrong type at runtimePureScript 函数在运行时给出错误的类型
【发布时间】: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

angleRefvelocityRef 是引用可变变量的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.xxlastPos.x)有以下类型

v2: Object[1]
  0: 127
  length: 1

而不是Number。同样的事情发生在ylastPos.y 的情况下。我猜想加上Number 类型的angle.x 会导致NaN。但为什么会这样?为什么 xlastPos.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中有错误。
  • 但问题不只是 xy。即使lastPos.xlastPos.y 最终是一个数组而不是Number 类型,但它们从readSTRef 函数中获取它们的值。另外值得一提的是,我的程序中有另一个函数也使用readSTRef,但那里的值是正常分配的,所以我真的很困惑为什么这只发生在moveHandler
  • getPageX 返回 jQuery 实例而不是数字
  • 我能做些什么来解决这个问题吗?
  • @GeorgeV.M.修复问题的拉取请求? :)

标签: jquery functional-programming purescript


【解决方案1】:

正如 Phill Freeman 和 Yury Tarabanko 在 cmets 中所建议的,事实证明 purescript-jquery 中的 getPageX/Y 返回了错误的类型。现在已更正,更新包后,程序按原样执行,newAngle 具有正确的值。

虽然getPageX/Y 的错误返回类型解释了为什么xy 不正确,但我仍然对为什么lastPos.xlastPos.y 也是错误类型感到困惑,即使它们是由readSTRef 分配的.直到现在我才意识到我愚蠢的大脑没有考虑清楚。 lastPos 存储最后一个鼠标位置,该位置也是getPageX/Y 获得的。所以这两种奇怪的类型都是由同一个错误引起的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2021-10-14
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    相关资源
    最近更新 更多