Haskell中while循环的等价语句是什么?

时间:2014-12-10 14:55:10

标签: haskell while-loop

作为Haskell的新手,我想知道如何1)计算某些东西,直到满足某个标准,然后2)返回计算值。

在我所知的语言中,你会使用while循环。你是怎么在Haskell做的?

4 个答案:

答案 0 :(得分:17)

您应该使用递归

func :: <function type>
func <arguments> = 
    if condition 
        then <recursive call>
        else computedValue

您将来会发现其他一些实用程序,例如until,它们可以帮助您解决此问题。最后,它实际上取决于循环和条件的语义。例如,如果条件只是&#34;直到我们到达列表的末尾&#34;您只需使用map或其中一个fold - 家庭功能。

答案 1 :(得分:6)

Haskell没有基于可变状态的while循环的内在等价物。

相反,您通常

  • 在一系列值上使用map系列函数来生成新的值范围
  • 在一系列值上使用filter系列函数来生成该范围的新子集,并满足某些条件
  • 使用fold系列函数来聚合该范围内的某些内容
  • 使用递归来做任何你想做的事情(当然,改变输入除外)。

当然,Haskell和库提供的功能可以让您的生活更轻松,但while循环可以被视为惯用/&#34;头等&#34;在命令式语言中,什么是惯用的/&#34;头等的&#34;在Haskell(和其他函数式编程语言)中是递归,映射,过滤和折叠。

答案 2 :(得分:6)

答案是递归。举一个迂腐的例子:

在Python中:

def fib(n):
    a = 0
    b = 1
    while n > 0:
        a, b = b, a + b
        n -= 1
    return b

在Haskell:

fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

或者等效地没有模式匹配

fib n = if n == 0 || n == 1 then 1 else fib (n - 1) + fib (n - 2)

或更有效率

-- the local variable fibs is an infinite list of all Fibonacci numbers
fib n = fibs !! n where fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

如果您希望执行类似于STDIN的阅读文字,直到您获得一行q,那么最简单的方式就是

import Control.Monad (unless)

prompt :: IO ()
prompt = do
    -- get input from user
    l <- getLine
    -- unless will execute its block if the condition is False
    unless (l == "q") $ do
        -- echo back to the user
        putStrLn $ "You entered: " ++ l
        prompt  -- recursive step here

或者在Python中

def prompt():
    l = input()
    while l != "q":
        # Assuming Python 3
        print("You entered: " + l)
        l = input()

答案 3 :(得分:0)

面临同样的问题,我需要将 C 转换为 Haskell。关键概念是条件和内置的 if-then-else 语句。

假设有一个 C 程序

int auto_drive (int speed) {
  int speed_limit = 90;
  while (speed > 0 & speed != speed_limit) {
    if (speed > speed_limit) {
      speed = speed - 1;
    } else {
      speed = speed + 1;
    }        
  }
  return speed;
}

将其转换为 Haskell:

auto_drive :: Int -> Int
auto_drive speed = mywhile (90,speed)

mywhile x =
  if condition x then mywhile (next_version_of x) -- if condition met, pass x to the function next_verion_of, next, recursion back to mywhile function 
  else final_version_of x -- otherwise, it would have the final speed

condition (speed_limit,speed) = speed > 0 && speed /= speed_limit 

next_version_of (speed_limit,speed) =
  if speed > speed_limit then (speed_limit,speed-1) else (speed_limit,speed+1) -- converge the speed to the speed limit

final_version_of (speed_limit,speed) = speed