I started with Haskell a few days ago. I have the following piece of code (recursive function):
totaltime t [x] = 0
totaltime t route = tbd + totaltime (t+tbd) (tail(route))
where tbd = timebetweendepartures (fst(route!!0)) (fst(route!!1)) t (snd(route!!1))
"route" is a list of tuples, e.g: [(3,1), (1,2), (5,2), (2,1)]
What I'm trying to do, is to add (0,0) to the route before the function even starts doing what it's supposed to do.
So if the parameter route is passed as [(3,1), (1,2), (5,2), (2,1)] then the function should receive it as [(0,0), (3,1), (1,2), (5,2), (2,1)]
I could just do totaltime t ((0,0):route)
, but since the function is recursive this won't work as intended.
Ideas are much appreciated!
Short answer: you can scope the function totaltime
into a where
clause, and expose another function that prepends the list with (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))
But that being said, the code is quite inelegant and probably unsafe:
!!0
and !!1
which are functions that are not total.Furthermore it is not very elegant you call fst
and snd
. We can introduce patterns in the head of the clause that ususally make it more elegant and easier to understand. We can thus rewrite our tt
function to:
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
so now we can use it like:
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
Of course in this case, it would be impossible to ever handle the empty list, since totaltime
prepends (0,0)
we have guarantees that the initial call is a call with at least one element, and we perform recursion on the direct tail, so that means that the list decreases with one at a time.
We still can however improve the function by using three arugments: the t
variable; the head of the list, the tail of the list, and rewrite it to:
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
Now the code is syntactically total, and furthermore it can boost efficiency (since we avoid unpacking some parts of the list twice.
We can still improve the code. Notice that we only take the first element of the head of the list (we do not use an y0
variable). So we can omit packing and unpackand and rewrite it to:
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
Now we save on unpacking tuples and it is more clear what we do.
You could wrap the function into an "entry-point" function that does the pre-processing of the externally received parameters:
totaltime t route =
totaltime' t ((0,0):route)
where
totaltime' t [x] = 0
totaltime' t route = .....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With