【问题标题】:Comprehension - Nested if-conditions in Haskell理解 - Haskell 中的嵌套 if 条件
【发布时间】:2014-06-04 19:57:05
【问题描述】:

我尝试熟悉 haskell 中的 if 条件语句

假设我有一个参数 x,我在 haskell 中尝试以下操作

functionname x = if x > 0 then x-5
                          if x-5 == 0 then 1
                          else if x-5 /= 0 then functionname x-5
                          else if x-5 <  then 0

所以,想法是从 x 中减去 5,检查结果是否为 0,如果是,则给 1。 如果不是,则使用表达式 x-5 再次调用该函数。 如果 x-5 的结果是否定的,则给出 0。

所以,我的问题是:这样对吗?因为当我尝试这样做时,我收到一条消息,例如输入“函数名”时出现解析错误。

我该如何解决这个问题? if-else 条件是否错误?


programm :: Int -> Bool

programm x |  x > 0 =
   if z == 0 then True
   else if z < 0 then False
   else programm z
   where
   z = z-2

programm x |  x < 0 =
   if z == 0 then True
   else if z > 0 then False
   else programm z
   where
   z = z+2

所以,我想有可能决定给定的数字是偶数。所以,我稍微修改一下你的解决方案。它是一样的,但在两个声明的开头我说:x > 0 = .... 和 x

当我把它交给编译器时,就会出现消息:异常。我在哪里做错了?

【问题讨论】:

  • 与其他一些语言不同,Haskell 中的每个if 都需要一个else

标签: haskell


【解决方案1】:

用警卫把事情说清楚:

functionname x
  | x > 0      = x - 5
  | x - 5 == 0 = 1
  | x - 5 /= 0 = functionname (x - 5)
  | x - 5 < 0  = 0

【讨论】:

  • 感谢您的回答。但是当我这样做时,编译器会抱怨第一行的结果 (| x > 0 = x - 5) 应该是布尔值。
【解决方案2】:

每个if 都需要有一个与之关联的else 子句。

第一个没有,最后一个也没有。 这工作得很好:

functionname x = if x > 0 then x-5
                 else if x-5 == 0 then 1
                 else if x-5 /= 0 then functionname x-5
                 else if x-5 < 0 then 0 else 1

【讨论】:

  • 感谢您的回答。但是当我这样做时,编译器会抱怨第一行的结果 (| x > 0 = x - 5) 应该是布尔值。
【解决方案3】:

所以,想法是从 x 中减去 5,检查结果是否为 0,如果 是的,然后给出 1。如果不是,则再次调用该函数 表达式 x-5。如果 x-5 的结果是否定的,则给出 0。

可能是这样写的:

functionname x =
    if x' == 0 then 1
    else if x' < 0 then 0
    else functionname x'
    where
    x' = x - 5

在这里,我使用where 子句将x' 本地定义为x - 5,然后将其用于测试和递归调用。您的第一个分支 if x &gt; 0 then x-5 没有出现在您对函数应该做什么的描述中(只要 x 大于零,它就会给出 x - 5 结果作为结果,这可能不是您想要的)。另外请注意,每个if 都需要一个else 和一个then

所以,我想有可能决定给定的数字是 甚至。所以,我稍微修改一下你的解决方案。它是一样的,但是,在 我说的两个声明的开头:x > 0 = .... 和 x

首先,在您的函数的第二个版本中,where 子句中的定义应该是z = x + 2,因为z = z + 2 不会终止。这是一个均匀性测试,您还想在x 而不是z 上执行测试。修复该问题后,您的嵌套条件解决方案应该可以正常工作(但是请注意,您没有处理 x == 0 的情况;第一个守卫应该是 x &gt;= 0)。不过,还有一种更优雅的方法来编写函数:

myEven :: Int -> Bool
myEven x = myEven' (abs x)
    where
    myEven' x
        | x == 0    = True
        | x < 0     = False
        | otherwise = myEven' (x - 2)

abs 是熟悉的绝对值函数,而 myEven' 相当于您原始定义的 x &gt; 0 分支。取x 的绝对值是避免编写两个几乎相等的分支来处理否定和非否定情况的最简单方法。

注意:虽然这可能只是一个学习练习,但如果您需要查找一个数字是否为偶数,Prelude 中有一个 even 函数可用。如果您需要测试其他数字的可除性,还有mod

【讨论】:

  • @user3097712 我更新了答案以匹配已编辑的问题。
猜你喜欢
  • 1970-01-01
  • 2019-08-20
  • 2023-01-31
  • 2013-03-29
  • 1970-01-01
  • 2019-09-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
相关资源
最近更新 更多