Skip to content

SChecked for gradual typing. #502

@tscholak

Description

@tscholak

Hi, @jul1u5 and I are trying to manually write a special singleton data type for gradually typed hasktorch.

We'd like a generic singleton datatype, SChecked a, that makes it possible to encode two situations:

  1. a is a singleton type itself and therefore checked by the compiler. For instance, a could be SNat or SBool.
  2. a is just a type like Natural or Bool and therefore unchecked by the compiler.

The nice thing about this is that values of type SChecked a can just be passed around like every other (singleton) value, and one can write programs that work with both forms of inputs, checked or unchecked. This is a huge convenience and makes it possible to gradually introduce stronger types.

We already have had success with specialized singleton types that distinguish between the two cases, see, e.g., https://github.com/hasktorch/hasktorch/blob/7bec8c01e85aa5ebf618f27122e88f50b5c75109/experimental/gradually-typed/src/Torch/GraduallyTyped/Layout.hs#L67, but we would like to have a more generic solution.

We have come up with the following encoding for SChecked a:

type Checked :: Type -> Type -> Type
data Checked a b = Checked a | Unchecked b

type SChecked :: Checked a Type -> Type
data SChecked checked where
  SUnchecked :: forall b. b -> SChecked @b ('Unchecked b)
  SChecked :: forall k a. Sing a -> SChecked @k ('Checked a)

type instance Sing = SChecked

instance (SingKind a, Demote a ~ a) => SingKind (Checked a Type) where
  type Demote (Checked a Type) = Checked a a
  fromSing (SUnchecked a) = Unchecked a
  fromSing (SChecked a) = Checked (fromSing a)
  toSing (Unchecked a) = SomeSing (SUnchecked a)
  toSing (Checked a) = withSomeSing a $ SomeSing . SChecked

This works, but the hidden kind annotation @b is a bit clumsy,

foo :: SChecked ('Checked 4)
foo = SChecked (SNat @4)

bar :: SChecked @Bool ('Unchecked Bool)
bar = SUnchecked True

We were wondering if someone has a better idea. Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions