Static Typing – the dangers of incomplete info

Ok, so I’m going to use this post – Making Illegal States Unrepresentable – and I’ll add my experience to it. For people that don’t know F# (or that don’t want to check all the post to see what’s the point), the idea is that he’s trying to construct a type that will only be valid if a user does at least an e-mail address or a postal contact. Then, he ends with the following type (I’m “inventing” a way to represent this type that’s close to Scala, but easier to read for people that don’t know Scala or Haskell or F#):

type Contact {
  Name: String
  AND Contact: ContactInfo
}

type ContactInfo {
  EmailOnly: EmailInfo
  OR PostOnly: PostalInfo
  OR EmailAndPost: EmailInfo with PostalInfo
}

// Types EmailInfo and PostalInfo have to be defined also

Then, he uses 13 lines to construct a ContactInfo, and another 12 to update a contact info. He ends up concluding that these complicated types are necessary because the logic is complicated. And that’s where we start to disagree.
(more…)

Please, use the right terms for “typing”…

Names matter. That’s one of the things that I learned, working multiple years on programming software. When you have something called “integration”, for example, that means different things for different people, that’s a recipe for disaster.

That’s why I get quite triggered when people use Untyped / Typed, Weak / Strong typed, Uni / Multi typed, to describe programming languages – because it means different things to different people, or are simply wrong. So let’s dive into it:

Untyped languages or languages without types are quite rare: Assembly is the most interesting example (there’s literally no types in Assembly: everything is a memory address, byte, word, etc). Some virtual machines’ bytecodes are also untyped. In this case, most languages are typed. Ruby, for example, have types, and you can dispatch different behavior depending on the type of the caller (because it’s a class-based object-oriented language). Clojure is also typed, because you can do type-based polymorphism with protocols using defprotocol and defrecord for example. You can also use deftype, and if there’s a specific command to define types, how can we call it “untyped”?

Weak / Strong typed is a term that’s hard to define. Some people say that it’s when you have pointers, because you can bypass the typing at all; others, when the compiler erases typing at run-time; some say that’s when the language tries to coerce and implicitly convert from one type to another, to try to figure out what you want…

Now, a language that allows you to bypass typing because you have pointers is called “memory unsafe”; if the compiler erases typing information, is called “type erasure”; coercion of course is called “coercion”, and can be “automatic” or “manual” coercion (for example, most languages try to coerce integers to decimals at some point); even the ability to convert between types is controversial: on Ruby and Scala, operators are also methods of the class (and, on Ruby, you can rewrite methods on classes that already exist, so automatic conversion is a user-defined feature) – so, please use the right term.

Unityped means a language that only have one type. I believe only some markup languages enter on this classification. Calling a language that have multiple types as unityped because someone imagined that all these multiple types can somewhat collapse into a single one is, at minimum, strange; and also, again, we do have a term for languages like Javascript, Ruby, Python, Smalltalk, and Clojure.
(more…)

Subtyping on functional languages

This is almost a new post on the Function SOLID series. It should be about the Liskov Substitution Princible, but before we talk about it it’s important to understand the concept of subtyping.

Subtyping in Dynamic languages like Clojure or in languages that do not have hierarchical typing like Haskell seems strange. But subtyping is not only a concept about object-oriented programming languages – it’s about restrictions, and the concept of variance. I’m going to try to explain both in this post

To begin with, we can say that a supertype is more generic than a subtype, but that’s not all. In truth, is all about properties that you can prove about a specific data. For example, if we use Clojure as a starting language you could say that the coll? is a property of maps and vectors, but vector? is a property that only applies to vectors. In practice, this means that coll? is a superclass of vector?.

(coll? []) ; => true
(coll? {}) ; => true

(vector? []) ; => true
(vector? {}) ; => false

(more…)