Comment by codebje

3 months ago

There's only one possible value of type Nine; there's only one possible value of type Unit. They're isomorphic: there's a pair of functions to convert from Nine to Unit and from Unit to Nine whose compositions are identities. Both functions are just constants that discard their argument un-inspected. "nineToUnit _ = unit" and "unitToNine _ = {9}".

You've made up your language and syntax for "type Nine int = {9}" so the rules of how it works are up to you. You're sort of talking about it like it's a refinement type, which is a type plus a predicate over values of the type. Refinement types aren't quite dependent types: they're sort of like a dependent pair where the second term is of kind Proposition, not Type; your type in Liquid Haskell would look something like 'type Nine = Int<\n -> n == 9>'.

Your type Nine carries no information, so the most reasonable runtime representation is no representation at all. Any use of the Nine boils down to pattern matching on it, and a pattern match on a Nine only has one possible branch, so you can ignore the Nine term altogether.

Why doesn't it seem exactly true?

It is an integer. It is in the definition. And any value should be equal to nine. By construction Nine could have been given the same representation as int, at first. Except this is not enough to express the refinement/proposition.

One could represent it as a fat pointer with a space allocated to the set of propositions/predicates to check the value of.

That allows to check for equality for instance.

That information would not be discarded.

This is basically a subtype of int.

As such, it is both a dependent type and a refinement type. While it is true that not all refinement types are dependent types, because of cardinality.

I think Maxatar response in the same thread puts it in words that are possibly closer to the art.

  • When does the predicate get tested?

    Also, it's not a dependent type. The type does not depend on the value. The value depends on the type.

    • The predicate gets tested every time we do type checking? It is part of the type identity. And it is a dependent type. Just like an array type is a dependent type, the actual array type depending on the length value argument.

      edit: I think I am starting to understand. In the implementations that are currently existing, Singleton types may be abstracted. My point is exactly to unabstract them so that the value is part of their identity.

      And only then we can deal with only types i.e. everything from the same Universe.

      2 replies →