Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 只修改一次函数的参数_Haskell - Fatal编程技术网

Haskell 只修改一次函数的参数

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),但是由于函数是递归的,所以它不能按预期工作 非常感谢您的想法

几天前我开始和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 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
where
tt t x[]=0;tt t(x0,)xys@=…
。(尽管如此,方向是正确的,所以+1)另一个选择是使用
非空的
。这似乎比额外的参数更清楚,并且可能会被优化掉。