Skip to content

Abstract types

tim-hardcastle edited this page Oct 15, 2023 · 37 revisions

In this page we will review the concept of "abstract types".

The essential point to remember is this. A concrete type is something a Charm value can have. An abstract type is a filter on what a variable can contain, or the parameter of a function, or the field of a struct.

So if for example x is a variable of type int?, this means that it can contain a value of type int or of type null. It cannot contain a value of type int?, because there are no values of type int?.

Nullable twins

As the previous example suggests, every one of the types we've met so far (except null itself) has an abstract "nullable twin", written <typename>?, which can contain either values of the type typename or the value NULL of type null: so for example int? contains either something of type int or it contains NULL. Of course this works for user-defined types too.

NOTE that you can't compare a non-null value with NULL, because you can't compare values of different types. So if you want to know if a nullable parameter/variable/field foo is equal to NULL, you must use the conditional expression foo in null to explicitly test its type membership.

Other sum types

The abstract type single contains all types that aren't tuple, including, please note, all other container types. single means anything that isn't a tuple, including pairs and sets and lists.

struct contains all structs, enum contains all enums, field contains all field names of structs, and label contains enum and field.

varchar

The abstract types above are supertypes of concrete types. varchar by contrast supplies us with a family of subtypes of strings: varchar(42) is a type containing strings with 42 or fewer characters.

Using abstract types

In functions and struct definitions, obviously you can just use an abstract type as you would use a concrete one.

def

Penguin = struct(name string, numberOfChicks int?, favoriteFood string?)

nullToZero(i int?) : 
    i in null : 0
    else : i

To widen or narrow a variable type you put the name of the concrete type after the name of the variable when declaring it. Note that this syntax is just like function / struct declarations: the syntax is <name> <type>.

var

couldBeInt int? = 42
couldBeBool bool? = NULL
shortString varchar(10) = "walrus"

If you don't do that, then the variable is automatically given the concrete type of the thing assigned to it. So for example if above we had just written couldBeBool = NULL, then the variable couldBeBool could not in fact be bool: it would be given the type null and could never contain anything but NULL.

🧿 Pipefish

Clone this wiki locally