[Haskell-cafe] Re: Debugging partial functions by the rules

Robert Dockins robdockins at fastmail.fm
Wed Nov 15 10:41:54 EST 2006

On Nov 15, 2006, at 9:48 AM, Jón Fairbairn wrote:

> Simon Peyton-Jones <simonpj at microsoft.com> writes:
>> | The problem I see is that head/fromJust errors are usually
>> |caused by *beginner* Haskellers, who don't know the
>> |techniques for statically avoiding them.
>> I don't agree.  My programs have invariants that I can't
>> always express in a way that the type system can
>> understand. E.g. I know that a variable is in scope, so
>> searching for it in an environment can't fail:
>>         head [ v | (n,v) <- env, n==target ] (Maybe if I had
>> an Oleg implant I could express all this in the type system
>> -- but I don't.)
> But instead of “blah (head [ v | (n,v) <- env, n==target ])
> blah”, you could write
> blah the_v_in_scope blah
> where (the_v_in_scope:_) =  [ v | (n,v) <- env, n==target ]
> and get a source-code located error message, couldn't you?
> It's not very high tech, but it's what you would write if
> head didn't exist, and it doesn't seem /that/ great an
> imposition.

Or how about.... ??

lookupVarible target env =
    case [ v | (n,v) <- env, n==target ] of
       (x:_) -> x
       _ -> assert False $ "BUG: Unexpected variable out of scope "++ 
(show target)++" in environment "++(show env)

  ... lookupVariable target env ....

It seems to me that every possible use of a partial function has some  
(possibly imagined) program invariant that prevents it from failing.   
Otherwise it is downright wrong.  'head', 'fromJust' and friends  
don't do anything to put that invariant in the program text.

Custom functions like the above 1) give you a great opportunity to  
add a meaningful assertion AND document the program invariant 2)  
attach some semantic meaning to the operation by naming it 3) make  
you think about what you're doing and help you avoid writing bugs in  
the first place 4) give you nice hooks for replacing your data- 
structure with a better one later, should it be necessary 5)  
encourage you to break down larger functions into smaller ones.

Big win if you ask me.  The frequent use of partial functions from  
the Prelude counters all of these advantages, and I avoid them as  
much as possible.

> -- 
> Jón Fairbairn                                  
> Jon.Fairbairn at cl.cam.ac.uk

Rob Dockins

Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG

More information about the Haskell-Cafe mailing list