简短回答:您可以将函数 totaltime 限定为 where 子句,并公开另一个在列表前添加 (0,0) 的函数:
totaltime t l = tt t ((0,0):l)
where tt t [x] = 0
tt t route = tbd + tt (t+tbd) (tail(route))
where tbd = timebetweendepartures (fst(route!!0)) (fst(route!!1)) t (snd(route!!1))
但话虽如此,代码很不优雅,而且可能不安全:
- 您没有为空列表定义案例;
- 用于空列表的情况是第二个子句,您在其中调用
!!0 和!!1,它们是不是total的函数。
此外,您调用fst 和snd 并不是很优雅。我们可以在子句的头部引入通常使其更优雅、更容易理解的模式。因此,我们可以将 tt 函数重写为:
tt t [] = ... # create a case for the empty list
tt t [x] = 0
tt t ((x0,_):xys@((x1,y1):_)) = tbd + tt (t+tbd) xys
where tbd = timebetweendepartures x0 x1 t y1
所以现在我们可以像这样使用它:
totaltime t l = tt t ((0,0):l)
where tt t [] = ... # create a case for the empty list
tt t [x] = 0
tt t ((x0,_):xys@((x1,y1):_)) = tbd + tt (t+tbd) xys
where tbd = timebetweendepartures x0 x1 t y1
当然,在这种情况下,处理空列表是不可能的,因为totaltime 前置(0,0) 我们保证初始调用是一个至少包含一个元素的调用,并且我们对直接尾部,这意味着列表一次减少一个。
然而,我们仍然可以通过使用三个参数来改进函数:t 变量;列表的头部,列表的尾部,并重写为:
totaltime t = tt t (0,0)
where tt _ _ [] = 0
tt t (x0,_) (xyh@(x1,y1):xyt) = tbd + tt (t+tbd) xyh xyt
where tbd = timebetweendepartures x0 x1 t y1
现在代码在语法上是完整的,而且它可以提高效率(因为我们避免将列表的某些部分解包两次。
我们仍然可以改进代码。请注意,我们只取列表头部的 first 元素(我们不使用y0 变量)。所以我们可以省略打包和解包并将其重写为:
totaltime t = tt t 0
where tt _ _ [] = 0
tt t x0 ((x1,y1):xyt) = tbd + tt (t+tbd) x1 xyt
where tbd = timebetweendepartures x0 x1 t y1
现在我们节省了拆包元组的工作,而且我们所做的工作更加清晰。