对于减法,相当于“+1”的是什么,因为“-1”被视为负数?

27

可能是重复问题:
柯里化减法

我开始我的第一个Haskell项目,这不是从教程中学来的,当然我会在最简单的事情上犯错。

我有以下代码:

moveUp y = modifyMVar_ y $ return . (+1)
moveDn y = modifyMVar_ y $ return . (-1)

我花了一些时间才明白为什么我的代码无法编译:我使用了“(-1)”,这被视为负数。括号不能帮助解决问题,因为它会将减号作为前缀,使得数字1成为第一个参数。

简而言之,这个代码的point-free版本是什么?

dec :: Num a => a -> a
dec x = x - 1

请参见 https://dev59.com/zm855IYBdhLWcg3wPBz6。 - Alexei Levenkov
3个回答

31
我相信你需要的是方便命名为subtract函数, 这个函数存在的原因正是你发现的那样:
subtract :: Num a => a -> a -> a

the same as flip (-).

Because - is treated specially in the Haskell grammar, (- e) is not a section, but an application of prefix negation. However, (subtract exp) is equivalent to the disallowed section.

如果您想在不使用像subtract这样的函数的情况下编写它们的无点式表示,您可以使用flip(-),正如Prelude文档所提到的那样。但是那有点丑。

7
如果上述的subtract太冗长,你可以尝试类似于(+ (-1))(-1 +)这样的方式。

2
这样做的好处是使我的两行代码对称,因为(+1)和(subtract 1)并排看起来不好。但是,这实际上并没有调用(-)。当然,Num认为这完全没问题,但如果我在使用集合时,这就不行了:将元素-1添加到集合中并不像删除元素1那样。Subtract更通用,但我会使用你的建议。然而,我将接受在这个问题中使用subtract或flip,因为这是一个更直接的答案。 - Niriel
我不确定我理解你的抱怨,因为(-)仅在Num实例上定义。(如果你有非交换的数字,这将是一个问题。) - Fixnum
6
由于您的数字似乎是“Enum”的实例,您也可以使用“succ”和“pred”。 - Fixnum

4
你可以使用标准Prelude中的subtract函数。
moveDn y = modifyMVar_ y $ return . (subtract 1)

您还可以使用翻转操作重新排列 - 的参数。

moveDn y = modifyMVar_ y $ return . (flip (-) 1)

+1... 我的版本没有翻转功能... - Alexei Levenkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接