【问题标题】:Rounding Negative Numbers in Haskell Using a Guard在 Haskell 中使用 Guard 舍入负数
【发布时间】:2018-01-13 11:46:24
【问题描述】:

我是 Haskell 的新手,所以我不太清楚如何操纵守卫中的操作顺序或对守卫中的“位置”表达式施加更多限制。 这是我在 Haskell 中的第一个程序,其中需要遵循一些神秘的标记方案,它会返回你的字母等级。它适用于所有非负输入,但轮函数似乎在负输入上失败。这是我的代码:

roundMark :: Float -> Integer
roundMark mark
    | mark2 < 0 = 0
    | mark2 > 100 = 100
    | otherwise = mark2
    where mark2 = round mark

letterGrade :: Float -> Char
letterGrade mark 
    | newMark < 48 = 'F'
    | newMark >= 48 && newMark < 65 = 'C'
    | newMark >= 65 && newMark < 79 = 'B'
    | otherwise = 'A'
    where newMark = roundMark mark

对于负输入,我得到错误

No instance for (Num (Float -> Char)) arising from a use of ‘-’
        (maybe you haven't applied a function to enough arguments?)

我想知道是否有一种方法可以限制我的 where 表达式在尝试使用 round 函数之前为负输入返回 0,或者我是否可以将我的防护置于条件中。

【问题讨论】:

  • 负数失败是什么意思?
  • 因为我得到错误 No instance for (Num (Float -> Char)) 由使用 '-' 引起(也许你没有将函数应用于足够的参数?)跨度>
  • 在问题中发布完整的错误。从表面上看,我看不出有什么会导致这样的错误。
  • 这看起来像是编译时错误,而不是运行时错误。它不应该只显示某些输入。它指向哪里?您不要在此代码中的任何地方使用-
  • 我尝试了使用 letterGrade (-1) 而不是 letterGrade -1 的函数。我不知道它们是不同的东西。谢谢。

标签: haskell functional-programming guard


【解决方案1】:
  1. round 是“银行家四舍五入”或“四舍五入”,但您可能 (?) 想要整数截断,例如 floor

  2. 在这种情况下舍入的目的是什么?负数仍然小于 48,并且仍然会产生 F,就像值 0 一样。

  3. 如果要将所有负数舍入为零,而不仅仅是负数 mark2 为零,则只需使用正确的变量:

.

roundMark :: Float -> Integer
roundMark mark
    | mark < 0 = 0      -- See this line, use `mark` vs `mark2`.
    | mark2 > 100 = 100
    | otherwise = mark2
    where mark2 = round mark

【讨论】:

  • 1.我想要四舍五入,所以我可以四舍五入到最接近的整数,例如 47.8 会导致 48,它会变成 C 而不是 F。
  • 但无论如何,谢谢你的帮助。我修好了我的,甚至不需要在哪里,只是为了让我的生活更简单。
  • 美国意义上的四舍五入(.5 及以上),然后加一并截断。
  • 我们不会在美国将 100 提高到 101,@ThomasM.DuBuisson。您可能的意思是添加 0.5 然后截断。
【解决方案2】:

这里的关键是letterGrade -1letterGrade (-1) 之间的区别。 letterGrade -1 表示取 letterGrade 的值并减去 1letterGrade (-1) 表示将函数 letterGrade 应用于值 -1。这是因为- 在这两种情况下都是运算符。 -1 不是数字“负数”。相反,它是由符号- 和整数值1 表示的运算符。问题是- 运算符有两种风格:一元和二元。为了区分- 的这两种用法,Haskell 的创建者决定使用(-1) 来表示一元运算符,它取给定数字的“负数”。没有括号,- 是二元减法运算符。

请参阅Why is the unary minus operator problematic in this expression: (- 2) 1? 及其相关问题以进一步讨论此主题。

【讨论】:

  • 大多数情况下,一元减号在实践中与括号一起使用,但更准确地说,它是一种语法形式(如 dolet 或 lambda),所以像 letterGrade $ -1 这样的表达式也是有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多