

The abject failure of weak typing - zoomerang
http://techblog.realestate.com.au/the-abject-failure-of-weak-typing/

======
dllthomas
I'd like to stress the point about wrapper types, which can even be usefully
employed in C. Note that - in C - this is not typedef (which is mostly
cosmetic), but rather wrapping primitives in otherwise empty structs. This has
no runtime cost and has the tremendous benefit that you won't mix up the
arguments to place_order(price_t, quantity_t) where you might to
place_order(int price, int quantity).

------
slashnull
I think what this planet needs is a comprehensive study of how different
typing techniques and schools of thought would solve different classes of
problems, because what I notice is that

1) definitions are hard, and don't mean much

2) there are many equivalences, and some idioms are conceptually very similar
across different type systems, and are just not implemented the same way. For
example, a it's a common hobby among FP weenies to show how most of the GoF
design patterns are one-liners in their languages of choice.

3) the scope of many typing disciplines is not the same; for example, unityped
languages work great for tasks of limited scope with lots of user interface
components, functional is historically used to write nice algorithms, and OOP
is an attempt at giving a distinct shape to software of very large scope (and
it happens to be a pain in the ass when the scope isn't that large)

------
EvenThisAcronym

        def compare(a: Int, b: Int): Int
    
        This one has not only 232 possible results, but an incalculable (232)264 possible implementations. Even if we are generous and only allow the inputs to be 0 or 1, we still have 2128 implementations. If the only meaningful return values are -1, 0 and 1, indicating “less than”, “equal” or “greater than”, then why would we embed them like specks of dust in a big desert of undefined behaviour?
    

I don't agree with this. This is not a "big desert of undefined behaviour".
The behaviour is defined along the entire spectrum of Integer values. "Less
than" maps to all values <= -1, "equal" maps to 0, and "greater than" maps to
all values >= 1. There's no undefined behaviour here.

------
sitkack
Implicitness as a source of error (in general) seems to raise its ugly head
over and over again.

------
jxf
This entire post seems to conflate "weak typing" with "dynamic typing". Both
are terms that seem to have a lot of common definitions, but they're
nevertheless distinct.

Weak typing usually implies a system where types get coerced easily:

    
    
        php -r "echo '4' + 4;"
        8
    

Dynamic typing, though, generally means that the type is associated with
runtime values. It doesn't mean that the typing is necessarily weak:

    
    
        ruby -e "'4' + 4"
        -e:1:in `+': no implicit conversion of Fixnum into String (TypeError)
    	from -e:1:in `<main>'

~~~
slashnull
That's cool and all but I think that the point of the article is that the
distinction is moot, because they just don't offer anything near the
expressive power of algebraic typing.

------
manicdee
It's a well written version of, "our software design was sloppy and our
programmers took shortcuts. Therefore language feature X is to blame."

    
    
      def findAddress(userId: String): String
      What does it do? Are you sure?
    
      Now lets look at another:
    
      def blah(foo: UserId): Address
    

What about

    
    
      def find_address_of_user( UserID )
    

or even better

    
    
      class User(Model):
         …
         address = our_models.AddressModel( … )
    

So you can use 'x = user.address' with no need to explicitly map between users
and addresses because the mapping is part of your data structure?

In some scenarios, Hungarian notation might make sense:

    
    
      def user_address(user):
    

In Hungarian notation you explicitly state what kind of data is expected, so
that you can easily determine if mistakes are being made in the code:

    
    
      billing_vcard = contact_vcard(customer.billing_contact)
    

as opposed to:

    
    
      display_vcard = contact_email(customer.billing_contact)
    

Of course, cue the irrational knee-jerk reaction to "Hungarian notation" by
people who don't understand what it actually is.

    
    
      OO lore has it that pattern matching is evil, and that subtype-polymorphism is the answer to all questions.
    

Not the OOD that I've been taught. Polymorphism is a tool, and it is as much
the answer to all questions as a screwdriver is the answer to all construction
projects.

That the author of this piece has found various languages educational in
presenting new ways of solving problems (with code smells, data model smells,
or sloppy architecture) is the biggest take-home message for me: don't be a
"Perl programmer" or a "Scala programmer". Be a software engineer, and make
sure you are aware of all the available architecture rules, modelling guides
and design patterns that have been developed over the years to make your job
easier.

Perhaps I'm missing something due to having read through the article too
quickly. Please educate me.

~~~
kenbot
Hi Manicdee! The point is that with any unityped representation you can come
up with, the name tells you nothing certain; any conclusions you think you can
draw from it are pixie-dust and moonshine. Even with nonsense names, the
argument and return types give you solid proof not only about what the method
does, but importantly what it _doesn't_ do.

There's no criticism implied of my colleagues at all -- I'm as culpable as
anyone. The point is though, we can make big improvements with types, without
paying a big cost.

You must have had good OOD teachers:
[http://c2.com/cgi/wiki?CaseStatementsConsideredHarmful](http://c2.com/cgi/wiki?CaseStatementsConsideredHarmful)
[http://c2.com/cgi/wiki?SwitchStatementsSmell](http://c2.com/cgi/wiki?SwitchStatementsSmell)

Cheers

~~~
manicdee
My apologies, I didn't intend to suggest that laziness and sloppiness were
attributes of the programmers, but evils imposed by time pressure.

Do I fight management to get the two weeks I'll need to write feature X
correctly, or just take the obvious shortcuts to get it done in 1 week?

Of course my laziness shows through because I haven't been in management's ear
for long enough beforehand that they decided to give me one week without
consulting with me ;)

I display this "lack of bottom-up management" failure mode consistently, I'm
more interested in writing code :\

As for my OOD teachers, I've had mountains of bad Perl and PHP code to wade
through, and the benefit of Stack Overflow and the Django Project to guide my
thinking on the matter.

Type systems do provide some compiler-level assistance in the march towards
coherent, well designed software, but they won't solve problems like

    
    
      def position_sprite( top_left: point, sprite: sprite)
    

When you provide the top_left of the wrong element (e.g.: confusing the top
left of the drawing space with the top left of the window or display area.

~~~
loup-vaillant
I believe phantom type should help with your example. At it's most naive, you
need a type for the points in window space, and a second type for the points
in drawing space. If you give the sprite a window_point, it will complain
about only accepting drawing_points. Now such errors are confined to a
conversion function.

With phantom types, a the Point "type" would be a function of types to types.
It helps when some operation work on all kinds of points: they can be
polymorphic with respect to the additional type.

    
    
      data Point a = Point Int Int
    
      draw_sprite  :: Point Drawing -> sprite -> Io ()
      draw_button  :: Point Window  -> sprite -> Io ()
    
      translate_point :: Point a -> Point b -> Point a
      translate_point (Point x y) (Point xt yt) =
          Point (x + xt) (y + yt)

------
tiquorsj
News flash!! Strong typing has benefits!

