Haskell 只修改一次函数的参数
几天前我开始和Haskell合作。 我有以下代码(递归函数): “路由”是元组列表,例如:[(3,1)、(1,2)、(5,2)、(2,1)] 我想做的是,在函数开始做它应该做的事情之前,向路由添加(0,0) 因此,如果参数route作为[(3,1),(1,2),(5,2),(2,1)]传递,那么函数应该作为[(0,0),(3,1),(1,2),(5,2),(2,1)]接收它 我可以只做Haskell 只修改一次函数的参数,haskell,Haskell,几天前我开始和Haskell合作。 我有以下代码(递归函数): “路由”是元组列表,例如:[(3,1)、(1,2)、(5,2)、(2,1)] 我想做的是,在函数开始做它应该做的事情之前,向路由添加(0,0) 因此,如果参数route作为[(3,1),(1,2),(5,2),(2,1)]传递,那么函数应该作为[(0,0),(3,1),(1,2),(5,2),(2,1)]接收它 我可以只做totaltime t((0,0):route),但是由于函数是递归的,所以它不能按预期工作 非常感谢您的想法
totaltime t((0,0):route)
,但是由于函数是递归的,所以它不能按预期工作
非常感谢您的想法 您可以将函数包装成一个“入口点”函数,对外部接收的参数进行预处理:
totaltime t route =
totaltime' t ((0,0):route)
where
totaltime' t [x] = 0
totaltime' t route = .....
简短回答:您可以将函数
totaltime
限定在where
子句中,并公开另一个在列表前面加上(0,0)
的函数:
但是,尽管如此,代码还是很不雅观,而且可能不安全:
- 您没有为空列表定义案例李>
- 空列表使用的大小写是第二个子句,在这里您调用
!!0和
这些函数不是全部函数!!1
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
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
现在代码在语法上是完整的,而且它可以提高效率(因为我们避免两次解包列表的某些部分)
我们仍然可以改进代码。请注意,我们只使用列表头的第一个元素(我们不使用y0
变量)。因此,我们可以省略打包和解包,并将其重写为:
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
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
totaltime t=tt t 0
其中tt[]=0
tt t x0((x1,y1):xyt)=tbd+tt(t+tbd)x1 xyt
其中tbd=部件之间的时间x0 x1 t y1
现在我们节省了解包元组的时间,我们做的事情就更清楚了。您真的需要空列表大小写吗?它似乎至少从一个元素(我们添加的伪元素)开始并且每次迭代只收缩一次。当然,也许我们可以添加空的大小写,然后完全避免使用包装器。@Thilo:就我个人而言,我更喜欢构造处理所有可能模式的函数(可以抛出“不应该发生”的
错误“
).但是就这样吧,这不是一个好主意。我会更进一步。在最后一次尝试中,没有真正的方法来定义空的大小写,我们甚至不需要它。我会将第一个列表元素作为另一个参数传递给tt
。例如tt t(0,0)l
wherett t x[]=0;tt t(x0,)xys@=…
。(尽管如此,方向是正确的,所以+1)另一个选择是使用非空的。这似乎比额外的参数更清楚,并且可能会被优化掉。