Functional programming

Chris Angelico rosuav at
Mon Mar 3 19:37:27 CET 2014

On Tue, Mar 4, 2014 at 4:27 AM, Steven D'Aprano
<steve+comp.lang.python at> wrote:
> On Tue, 04 Mar 2014 02:01:47 +1100, Chris Angelico wrote:
>> This is why it's tricky to put rules in based on type inference. The
>> programmer's intent isn't in the picture.
> Of course it is. If I assign 23 to variable x, that signals my intent to
> assign an int to x. By Occam's razor, it is reasonable to extrapolate
> that intent to mean "x is an int", rather than "an int, or a list" or "an
> odd int larger than 7 but smaller than 25", or "any int except 13". Type
> inference picks the type which involves the fewest additional
> assumptions. The programmer can always over-ride the type inference by
> explicitly stating the type.

Yes, and that's fine for most purposes. The problem isn't the
inference, the problem is when rules are created based on that kind of
guess - when the programmer's subsequent actions are governed by a
guess the compiler takes.

x = 23 # Compiler goes: Okay, x takes ints.
x += 5 # Compiler: No prob, int += int --> int
x = str(x) # Compiler: NO WAY! str(int) --> str, not allowed!

It's fine and correct to infer that x is an int, x is an int, x is a
str. It's *not* okay to make the third line a SyntaxError because you
just put a str into an int variable.

>> If Python ever acquires that
>> kind of restriction ("here's a list that can contain only this type /
>> these types of object"), I would hope that it's left up to the
>> programmer, not the compiler, to stipulate.
> That's not type inference. That's ancient and annoying obligatory type
> declarations as used by ancient languages with primitive type systems,
> like Pascal and C.

And that's exactly what Haskell apparently has, with homogeneous lists
and no easy way to say that it can take more types.

Python's handling is: A list can hold anything.

Pike's handling is: An array can hold anything, unless you specify
otherwise. You can specify whatever you can code:
array(int(1000..2000) | string('a'..'z') | float) foo = ({1234,
"abcd", 1.2});

Haskell's handling apparently is: A list/array can hold one thing and
one thing only. That 'thing' can be a union, but then you need to be
REALLY explicit about which side is which. It's not possible to
sub-specify a type (like the "string('a'..'x')" type in Pike that will
take only strings with nothing but the first 24 lower-case letters -
not that I've ever needed that), but the compiler can work out
everything else.

The way I see it, Python's form is fully dynamic and open, Pike's is
fully dynamic and the programmer's allowed to explicitly close things,
and Haskell's is rigidly tight. That's not to say that tight is a bad
thing (it's probably good for learning under), but personally, I'd
rather have the freedom.


More information about the Python-list mailing list