Skip to content

Union and Intersection types

Jonathan edited this page Mar 9, 2018 · 1 revision

Union Types

val input: String|Int = ...

match(input) {
  String -> println(#{"Input '{0}' is a String" where 0 -> input})
  Int -> println(#{"Input '{0}' is an int" where 0 -> input})
}

Also union type may be used as alternative to Option<A> and A?:

val input: String|() = ...

if (input !is ()) {
    // input inferred to String
    println(#{"Input is present, input: {0}" where 0 -> input})
} else {
    println("Input is not present")
}

When an instance check is satisfied, this type is removed or added to inferred types, also there is a maybe list of inferred types, example:

val entity = Person|Dog|Cat|() = ...
if (entity is Person) {
    // Inferred to Person, but maybe Dog|Cat|()
}
if (entity !is Person) {
    // Inferred to Dog|Cat|()
}

When type is inferred to X but maybe types is not empty, then X may also be of one or all the types, if inferred type is final then the maybe list is empty, meaning that checks against this type will be considered an error:

val number: Int|Long|Double|() = ...

if (number is Int) {
    if (number is Long) { // Error: 'number' variable cannot be of Long type here because the inferred type `Int` is final.
    }
}

But this is correct:

interface Printer { fun print(v: Char) }
interface Reader { fun read(): Char }

val pr = Printer|Reader|() = ...
if (pr is Printer) {
    if (pr is Reader) { // Correct
    }
}

Intersection types

val rw: Readable&Writable = ...
rw.write(bytes)
val read = rw.read() // read = bytes
Clone this wiki locally