在 PureScript 中比较整数元组有什么错误?
What do I wrong comparing a tuple of integers in PureScript?
调试鼠标移动事件的事件处理程序,我编写了以下代码:
unless (scrollDelta == Tuple 0 0) $ trace (show scrollDelta) \_ -> do ...
然后我得到控制台输出
Tuple 0 0
这背后的想法是在用户按下第一个鼠标按钮时移动鼠标时保存鼠标位置的差异。
这是编译器错误吗?
我的解决方法是将 scrollDelta
的类型更改为 Maybe (Tuple Int Int)
,其中 Nothing
表示“按下按钮时没有鼠标移动”,而不是 Tuple 0 0
,这有效。
你的问题是评估和执行之间的区别。
当你写这样的东西时:
Console.log "foo"
与您的直觉相反,这 而不是 实际上会打印任何内容到控制台。相反,这会创建一个“动作”,它必须在稍后的某个时间点被“执行”,并且只有到那时它才会向控制台打印一些东西。
相反,同一个动作实际上可以“执行”多次,从而产生多种效果:
printFoo = Console.log "foo"
-- ^ Nothing is printed at this point
main = do
printFoo
printFoo
printFoo
-- ^ "foo" is printed three times
- “评估”正在创建“操作”
- “执行”是运行“行动”,以产生它产生的任何效果
在上面的示例中,评估发生一次,但执行 - 三次。
unless
的工作方式,它需要一个 Boolean
值和一个“操作”,并且它 returns 另一个“操作” :
dontPrintFoo = unless true printFoo
当您执行操作dontPrintFoo
时,它将是unless
返回的操作,它将检查Boolean
参数并选择不 执行动作 printFoo
.
但是假设你有更复杂的场景:
dontPrintFoo = unless true $ if qux then printFoo else printBar
此处,unless
的两个参数在传递给 unless
之前必须“求值”(而不是“执行”!)。这意味着 qux
的值和 if
/then
的结果是在 在 调用 unless
之前计算的。但是当从 main
.
调用整个结果时,结果操作将在稍后执行
但是trace
很特别。魔法。即使它产生了效果(打印到控制台),编译器仍认为它是一个纯函数。喜欢 2 + 3
或喜欢 if qux then foo else bar
。这样做是为了方便调试:这样您就可以在纯的、无效的代码中插入跟踪。
这意味着 trace
在“评估”时评估,而不是“执行”。这意味着它在 之前被评估 unless
甚至被调用,因此无论 Boolean
参数是 true
还是 false
都会被评估].
如果您希望跟踪仅在 unless
决定执行操作时才起作用,请尝试 traceM
:
unless (...) do
traceM (show scrollDelta)
foo
bar
调试鼠标移动事件的事件处理程序,我编写了以下代码:
unless (scrollDelta == Tuple 0 0) $ trace (show scrollDelta) \_ -> do ...
然后我得到控制台输出
Tuple 0 0
这背后的想法是在用户按下第一个鼠标按钮时移动鼠标时保存鼠标位置的差异。
这是编译器错误吗?
我的解决方法是将 scrollDelta
的类型更改为 Maybe (Tuple Int Int)
,其中 Nothing
表示“按下按钮时没有鼠标移动”,而不是 Tuple 0 0
,这有效。
你的问题是评估和执行之间的区别。
当你写这样的东西时:
Console.log "foo"
与您的直觉相反,这 而不是 实际上会打印任何内容到控制台。相反,这会创建一个“动作”,它必须在稍后的某个时间点被“执行”,并且只有到那时它才会向控制台打印一些东西。
相反,同一个动作实际上可以“执行”多次,从而产生多种效果:
printFoo = Console.log "foo"
-- ^ Nothing is printed at this point
main = do
printFoo
printFoo
printFoo
-- ^ "foo" is printed three times
- “评估”正在创建“操作”
- “执行”是运行“行动”,以产生它产生的任何效果
在上面的示例中,评估发生一次,但执行 - 三次。
unless
的工作方式,它需要一个 Boolean
值和一个“操作”,并且它 returns 另一个“操作” :
dontPrintFoo = unless true printFoo
当您执行操作dontPrintFoo
时,它将是unless
返回的操作,它将检查Boolean
参数并选择不 执行动作 printFoo
.
但是假设你有更复杂的场景:
dontPrintFoo = unless true $ if qux then printFoo else printBar
此处,unless
的两个参数在传递给 unless
之前必须“求值”(而不是“执行”!)。这意味着 qux
的值和 if
/then
的结果是在 在 调用 unless
之前计算的。但是当从 main
.
但是trace
很特别。魔法。即使它产生了效果(打印到控制台),编译器仍认为它是一个纯函数。喜欢 2 + 3
或喜欢 if qux then foo else bar
。这样做是为了方便调试:这样您就可以在纯的、无效的代码中插入跟踪。
这意味着 trace
在“评估”时评估,而不是“执行”。这意味着它在 之前被评估 unless
甚至被调用,因此无论 Boolean
参数是 true
还是 false
都会被评估].
如果您希望跟踪仅在 unless
决定执行操作时才起作用,请尝试 traceM
:
unless (...) do
traceM (show scrollDelta)
foo
bar