# Avoiding partial functions

### From HaskellWiki

(Difference between revisions)

(irrefutable pattern match on (:)) |
(init, last) |
||

Line 22: | Line 22: | ||

</haskell> |
</haskell> |
||

+ | == init, last == |
||

+ | |||

+ | You may replace |
||

+ | <haskell> |
||

+ | if null xs |
||

+ | then g |
||

+ | else h (init xs) (last xs) |
||

+ | </haskell> |
||

+ | by |
||

+ | <haskell> |
||

+ | case xs of |
||

+ | [] -> g |
||

+ | y:ys -> uncurry h $ viewRTotal y ys |
||

+ | |||

+ | viewRTotal :: a -> [a] -> ([a], a) |
||

+ | viewRTotal x xs = |
||

+ | forcePair $ |
||

+ | case xs of |
||

+ | [] -> ([], x) |
||

+ | y:ys -> case viewRTotal y ys of (zs,z) -> (x:zs,z) |
||

+ | |||

+ | forcePair :: (a,b) -> (a,b) |
||

+ | forcePair ~(a,b) = (a,b) |
||

+ | </haskell> |
||

== (!!) == |
== (!!) == |

## Revision as of 12:00, 5 June 2012

There are several partial functions in the Haskell standard library. If you use them, you always risk to end up with an undefined. In this article we give some hints how to avoid them, leading to code that you can be more confident about.

For a partial function f the general pattern is: Whereever we write "check whether x is in the domain of f before computing f x", we replace it by combination of check and computation of f.

## Contents |

## 1 head, tail

You should replace

if null xs then g else h (head xs) (tail xs)

by

case xs of [] -> g y:ys -> h y ys

## 2 init, last

You may replace

if null xs then g else h (init xs) (last xs)

by

case xs of [] -> g y:ys -> uncurry h $ viewRTotal y ys viewRTotal :: a -> [a] -> ([a], a) viewRTotal x xs = forcePair $ case xs of [] -> ([], x) y:ys -> case viewRTotal y ys of (zs,z) -> (x:zs,z) forcePair :: (a,b) -> (a,b) forcePair ~(a,b) = (a,b)

## 3 (!!)

You should replace

if k < length xs then xs!!k else y

by

case drop k xs of x:_ -> x [] -> y

length

## 4 irrefutable pattern match on (:)

You should replace

if k < length xs then let (prefix,x:suffix) = splitAt k xs in g prefix x suffix else y

by

case splitAt k xs of (prefix,x:suffix) -> g prefix x suffix (_,[]) -> y