Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is take a total function

take (-1) [] is [].

What are the reasons to prefer this over a partial function, that is, an error?

Are there use cases where this property is exploited?

like image 326
false Avatar asked Nov 27 '14 17:11

false


2 Answers

take and drop are similar to the left-substring and right-substring functions, and it's proven in practice to be convenient for those not raise an error for negative or invalid lengths.

For example - a padding function:

pad :: Int -> String -> String
pad n str = (repeat (n - length str) ' ') ++ str

and here is a variant to pad with another string:

padWith :: String -> Int -> String -> String
padWith field n str = (take (n - length str) field) ++ str
like image 124
ErikR Avatar answered Nov 08 '22 17:11

ErikR


Splitting a list in chunks of (at most) n pieces requires take to be total:

chunks n [] = []
chunks n xs = take n xs : chunks n (drop n xs)

Also, the current definition ensures

take n xs ++ drop n xs == xs

for any n and xs.

Arguably, we should have both takeAtMost and takeAtLeast, the latter being the partial variant (or instead returning Maybe).

A similar concern arises from zip, which is total as well, even when applied to lists of unequal length. Still, that is frequently exploited in the idiom zip [1..] xs which pairs every element of the list with its own index.

Keep however in mind that I am not arguing that a total function is always the preferred one. On many, many programming tasks obtaining a bug-revealing exception is a bliss compared with obtaining the wrong result and having no idea about where the bug is. Or even worse, getting a wrong yet plausible result, and not even discovering there is a bug.

like image 43
chi Avatar answered Nov 08 '22 17:11

chi