-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SChecked
for gradual typing.
#502
Comments
What you really want is this, I think: type Checked :: Type -> Type
data Checked a where
Checked :: a -> Checked a
Unchecked :: forall b -> Checked b That is, type Checked :: Type -> Type
data Checked a where
Checked :: a -> Checked a
Unchecked :: Proxy b -> Checked b
-- This is just to appease the injectivity check on Demote
type Unchecked :: Type -> Type
newtype Unchecked a = MkUnchecked { unUnchecked :: a }
type SChecked :: Checked a -> Type
data SChecked checked where
SUnchecked :: forall b. b -> SChecked @b ('Unchecked 'Proxy)
SChecked :: forall k a. Sing a -> SChecked @k ('Checked a)
type instance Sing = SChecked
instance (SingKind a, Demote a ~ a) => SingKind (Checked a) where
type Demote (Checked a) = Unchecked (Demote a)
fromSing (SUnchecked a) = MkUnchecked a
fromSing (SChecked a) = MkUnchecked (fromSing a)
toSing (MkUnchecked a) = withSomeSing a $ SomeSing . SChecked
foo :: SChecked ('Checked 4)
foo = SChecked (SNat @4)
bar :: SChecked ('Unchecked @Bool 'Proxy)
bar = SUnchecked True A key step here is using a different type ( type Checked :: Type -> Type
data Checked a where
Checked :: a -> Checked a
Unchecked :: forall b. Checked b
-- This is just to appease the injectivity check on Demote
type Unchecked :: Type -> Type
newtype Unchecked a = MkUnchecked { unUnchecked :: a }
type SChecked :: Checked a -> Type
data SChecked checked where
SUnchecked :: forall b. b -> SChecked ('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) where
type Demote (Checked a) = Unchecked (Demote a)
fromSing (SUnchecked a) = MkUnchecked a
fromSing (SChecked a) = MkUnchecked (fromSing a)
toSing (MkUnchecked a) = withSomeSing a $ SomeSing . SChecked
foo :: SChecked ('Checked 4)
foo = SChecked (SNat @4)
bar :: SChecked ('Unchecked @Bool)
bar = SUnchecked True The downside here is that the argument to type UncheckedV :: forall b -> Checked b
type UncheckedV b = 'Unchecked @b Does this look like it would work better in your use case? |
Hi @goldfirere, thank you for this very detailed response and the great ideas!
Maybe it's a bit pedantic, but I wanted to make a lawful |
Hard to know whether that identity would be important -- but I appreciate your interest in upholding it. In any case, even if you want to remember the checked-status after calling |
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:a
is a singleton type itself and therefore checked by the compiler. For instance,a
could beSNat
orSBool
.a
is just a type likeNatural
orBool
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
:This works, but the hidden kind annotation
@b
is a bit clumsy,We were wondering if someone has a better idea. Thanks!
The text was updated successfully, but these errors were encountered: