我正在Haskell编写一个小型学校作业,以确定两个给定日期之间的距离。我写了一个粗略的函数来循环日期,但是我无法用函数式编程的方式来编写循环。我之前只做过程序和OOP编程。我不知何故需要存储有关我调用nextDate函数多少次的信息,但是Haskell不允许我在函数内部引入变量。这是到目前为止我提出的代码。完全不是Haskelly ...
nextDate year month day =
if day + 1 < 31
then (year,month, day+1)
else if month + 1 < 12
then (year, month + 1, 1)
else (year +1,1,1)
calculateDifference year month day year2 month2 day2 =
let x = 0
if year == year2 && month == month2 && day == day2 then x
else
nextDate(year, month, day)
x = x + 1
-- How I would do it in Python
-- x = 0
-- while((tuple1) != (year2, month2, day2)):
-- x += 1
-- tuple1 = nextDate(tuple1)
-- print(x)
答案 0 :(得分:2)
如果要跟踪调用该函数的次数,则需要提供该输入作为输入。没有其他方法可以执行此操作,因为Haskell仅允许您使用传递给函数的参数。
例如,假设我想计算一个阶乘,但我想跟踪它采取了多少步骤。我的函数签名看起来像这样:
factorial :: Int -> (Int, Int) -- Takes a number, returns the number and recursion count
factorialInternal :: (Int, Int) -> (Int, Int) -- This actually does the recursion
,然后定义如下所示:
factorial n = factorialInternal (n, 0)
factorialInternal (1, n) = (1, n + 1)
factorialInternal (x, n) = let (y, z) = factorialInternal (x-1, n) in (x * y, z + 1)
本质上,跟踪递归量的参数在每个级别上都会增加,然后成为factorial
输出的一部分。
它肯定有助于创建接口函数,这样您在使用函数时就不必手动输入起始递归级别(无论如何始终为零)。函数签名的示例如下:
-- The function you call
calculateDifference :: (Int, Int, Int) -> (Int, Int, Int) -> Int
-- What the calculateDifference function calls (the third parameter is the recursion counter)
calculateDifferenceInternal :: (Int, Int, Int) -> (Int, Int, Int) -> Int -> Int
从这里,您应该能够弄清楚如何实现calculateDifference
和calculateDifferenceInternal
。
编辑:正如amalloy指出的那样,一个更好的解决方案是只输出计数器,而不要输入一个计数器:因此,factorialInternal :: (Int, Int) -> (Int, Int)
可以代替factorialInternal Int -> (Int, Int)
。定义如下:
factorialInternal 1 = (1, 0)
factorialInternal n = let (x, y) = factorialInternal (n - 1) in (n * x, y + 1)