Is `false` a bottom type in Verse?

Studying the public verse APIs I run into Err<native><public>(Message:[]char)<computes>: false function which returns false as its type.

I haven’t found any explicit mention in the documentation regarding this type. So I wondered if false is officially blessed as the bottom type in Verse.

That’s right, false is the bottom type that has no possible values, and any is the top type which contains all possible values.

2 Likes

Speaking of any. What is the type of any actually?

Its instance is an existential, basically a box that can hold anything, but I’m not sure about the actual type. Is it a special interface of some sort or just a special built-in type?

Furthermore, are there any plans to permit dynamic downcasts from an instance of type any?

Something: any = ...
if (Number := int[Something]) {} # this is currently not permitted.

Using any to box multiple different types and then dynamically restore their actual type seems to be currently not permitted. This is a huge hole in the usefulness of any.

any includes values that aren’t comparable at runtime, and so we cannot support dynamic downcasts from it. The type system needs it, but it’s not actually useful for writing code.

comparable is a much more useful nearly-top type that includes all runtime comparable values, so we could support dynamic downcasts from it. However, that is not yet implemented.

Coming from Swift this is very surprising to me. Swift’s any type is the top most type and you can dynamically downcast to the boxed type.

let any: Any = 42 // `Int` inside the `Any` existential

if let string = any as? String {} // dynamic cast will fail

if let integer = any as? Int { 
  print(“works”, integer) 
}

Verse’s comparable is another type that I have multiple questions about. Why is it called comparable while it only supports equality checks such as with the = and <> operators? Again, that’s another thing that slightly bends my mind after years of Swift experience. In Swift we have the Equatable protocol, but we also have the Comparable protocol.

  • Equatable is used to add equality capability to a type via a static implicit == infix function, while the != is implemented by the the stdlib.
  • Comparable extends the capability of Equatable and adds comparison via the < infix operator. The Comparable protocol is more useful for sorting data than comparing their equality.
// Foo is probably not implicitly equatable nor comparable
struct Foo {
  let tuple: (Int, Int, Int, Int)
}

struct Bar: Equatable {
  let number: Int
  // the compiler can synthesize the following, but we can also implement it manually if needed
  static func == (lhs: Self, rhs: Self) -> Bool {
   lhs.number == rhs.number
  }
}

extension Bar: Comparable {
  // same story here to add comparability
  static func < (lhs: Self, rhs: Self) -> Bool {
    lhs.number < rhs.number 
  } 
}

That said, it’s up to the developer to decide which types are Equtable, Comparable, Hashable etc.

Verse’s choice not to support equality of structs and enums appears very stange to me. I hope it’s just another “not yet implemented” story. :slight_smile:

Long story short I find it strange not being able to dynamically downcast from any. That operation equals Swift’s as? syntax and should fail if the type we’re trying to restore is not compatible. Erasing the original type and not being able to restore it later on seems like a dead end to me. :face_with_raised_eyebrow: Using comparable as a form of a workaround is not ideal as I previously mentioned, not every type should actually support equality. I can’t even imagine how to build my own type erasure box without the dynamic downcast capability.

That’s just my personal Swift’s experts opinion. I’m not a compiler developer but a heavy Swift user and pioneer and looking to become an expert in Verse as well. Feel free to disagree with anything, but I’d also would love if you could share some of the design decisions made for Verse and the reasonings behind them. :nerd_face:

3 Likes