作为Haskell的新手,我想知道如何1)计算某些东西,直到满足某个标准,然后2)返回计算值。
在我所知的语言中,你会使用while循环。你是怎么在Haskell做的?
答案 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