Skip to content

Singletonize functions that already use singletons #460

Description

@greatBigDot
$(singletons [d|
  data Nat = Z | S Nat
  data Vec n a where
    VNil  :: Vec 'Z a
    (:::) :: a -> Vec n a -> Vec ('S n) a
|])

I frequently find myself wanting to singletonize functions that already use singletons, but since singletons can't do that I have to write it by hand. E.g., consider the vector version of replicate:

vReplicate :: SNat n -> a -> Vec n a
vReplicate SZ _ = VNil
vReplicate (SS n) x = x ::: vReplicate n x

It'd be nice if wrapping that in $(singletons [d| ... |]) automatically generated:

type family VReplicate (n :: Nat) (x :: a) :: Vec n a where
  VReplicate 'Z _ = 'VNil
  VReplicate ('S n) x = x '::: VReplicate n x

sVReplicate :: SNat n -> Sing (x :: a) -> SVec (VReplicate n x)
sVReplicate SZ _ = SVNil
sVReplicate (SS n) x = x :%:: sVReplicate n x

As well as all the defunctionalization symbols and whatnot.

Instead, it tries to generate things like sVReplicate :: Sing (n' :: SNat n) -> ...; as far as I'm aware, meta-singleton types like that are never actually useful.

I guess one problem would be in telling whether or not a type is a singleton, so you know when to prepend an S; would you need to add a typeclass to store the relationship between a type and its singleton type or something?

(My apologies if this idea doesn't generalize to more advanced stuff; I've only tried it on simple things like vReplicate, and so far there's always been a unique obvious way to singletonize everything manually.)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions