Functional programming

Chris Angelico rosuav at gmail.com
Tue Mar 4 01:04:55 EST 2014


On Tue, Mar 4, 2014 at 4:35 PM, Steven D'Aprano <steve at pearwood.info> wrote:
> On Tue, 04 Mar 2014 05:37:27 +1100, Chris Angelico wrote:
>> 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.
>
> It won't be a Syntax Error, it will be a compile-time Type Error. And,
> yes, it is fine. That's the point of static typing! The tradeoff of being
> able to detect a whole lot of errors *at compile time* is that you give
> up the ability to re-use the same variable for different types in a
> single scope. (You can have an x which is a string elsewhere, just not in
> this scope where it is an int.)

Okay, a compile-type type error, same difference. What I'm saying is
that the auto-detection can't know what else you plan to do. If you
explicitly say that this is an int, then yes, that should be
disallowed; if you explicitly say that it's either an int or a float,
then you should be able to have either, but not a string. (C does this
with explicitly tagged unions, usually. Python and Pike do it by
simply allowing multiple types in the same slot.)

> That Haskell has homogeneous lists is not a property of the type system,
> but a design choice. I'm sure Haskell will also have a tuple or record
> type that allows fields of different types.

If it's not the list type, pick some other. It's not uncommon to want
to have a record that has different types (C does this with struct,
C++ has a few more ways to do it); what I'm finding odd is that
whatever goes into it first is specifying for everything else.

> I have not used Haskell enough to tell you whether you can specify
> subtypes. I know that, at least for numeric (integer) types, venerable
> old Pascal allows you to define subtypes based on integer ranges, so I'd
> be surprised if you couldn't do the same thing in Haskell.
>
> The flexibility of the type system -- its ability to create subtypes and
> union types -- is independent of whether it is explicitly declared or
> uses type inference.

I'm not sure how you could have type inference with subtypes. How does
the compiler figure out what subtype of integers is acceptable, such
that it can reject some?

x = 5
x = 7
x = 11
x = 17
x = 27

Should the last one be rejected because it's not prime? How can it
know that I actually wanted that to be int(3..20)? That's why I see
them as connected. All sorts of flexibilities are possible when the
programmer explicitly tells the compiler what the rules are.

> Hey, I'm a Python programmer! You don't have to sell me on the benefits
> of dynamic typing. Before Python, my language of choice was Apple's
> Hyperscript, which is untyped -- everything, and I mean everything, is a
> string in Hyperscript. It works remarkably well, so long as you don't
> care about speed. But even in the late 80s or early 1990s, on single-core
> CPUs running at a piddly 7.8 MHz (compared to about 1000 MHz for desktops
> today), you could get acceptable performance for a remarkable range of
> applications.
>
> But don't be fooled, those benefits aren't free. Static typing has
> benefits too.

For me, that untyped language was REXX. One data type (the string),
and a special feature of variable names to handle what most people
would do with arrays/lists/mappings/dicts/etc/etc/etc. (Or, of course,
you do what you'd presumably do in Hyperscript, and implement an array
of words as a string that you separate on ' '. VX-REXX had a neat
'initializer format' where you simply prefix every element with the
separator - that is to say, the first character of the string is the
separator. It nests perfectly and is pretty convenient to type. A
little obscure for most people, though.) Was also my first taste of
arbitrary-precision arithmetic. C could cream it as long as I didn't
need anything over 2**32 or anything I can't do in a double-precision
float, but I could calculate 200! with clean brute-force code and it'd
work perfectly.

Static and dynamic typing both have their uses. But when I use static
typing, I want to specify the types myself. I'm aware that's a matter
of opinion, but I don't like the idea of the compiler rejecting code
based on inferred types.

ChrisA



More information about the Python-list mailing list