[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