-
Notifications
You must be signed in to change notification settings - Fork 37
Open
Description
I'm trying to define a fixed-length vector type, indexed by Peano numbers, then promote the vector, and define an append operation on that vector, both at the type and the value level. I need the defunctionalisation symbols because I'm going to use this family later in a more complicated function, which I'll also want to promote.
{-# LANGUAGE TemplateHaskell #-}
import Data.Singletons.TH
import Data.Singletons.TH.Options
$( withOptions defaultOptions {genSingKindInsts = False}
$ singletons
[d|
data N = Z | S N
(++) :: N -> N -> N
Z ++ m = m
S n ++ m = S (n ++ m)
type Vec :: N -> Type -> Type
data Vec n a where
VNil :: Vec 'Z a
(:.) :: a -> Vec n a -> Vec ('S n) a
|]
)
$( singletons
[d|
(+++) :: Vec n a -> Vec m a -> Vec (n ++ m) a
VNil +++ ys = ys
(x :. xs) +++ ys = x :. (xs +++ ys)
|]
)GHC refuses to compile the second splice, with the following error:
src/Lambda/TypeLevel/Example.hs:24:2: error: [GHC-73138]
• Illegal type synonym family application ‘n ++ m’ in instance:
Apply
@(Vec n a)
@(Vec m a ~> Vec (n ++ m) a)
((+++@#@$) @n @a @m)
a6989586621679086404
• In the type instance declaration for ‘Apply’
|
24 | $( singletons
| ^^^^^^^^^^^^...
The generated code (cleaned up) is:
(+++) :: Vec n a -> Vec m a -> Vec (n ++ m) a
(+++) VNil ys = ys
(+++) (x :. xs) ys = x :. (xs +++ ys)
type (+++@#@$) :: (~>) (Vec n a) ((~>) (Vec m a) (Vec (n ++ m) a))
data (+++@#@$) :: (~>) (Vec n a) ((~>) (Vec m a) (Vec (n ++ m) a)) where
(:+++@#@$###) ::
(SameKind (Apply (+++@#@$) arg) ((+++@#@$$) arg)) => (+++@#@$) a
type instance Apply (+++@#@$) v1 = (+++@#@$$) v1
instance SuppressUnusedWarnings (+++@#@$) where
suppressUnusedWarnings = snd ((,) (:+++@#@$###) ())
type (+++@#@$$) ::
Vec n a ->
(~>) (Vec m a) (Vec (n ++ m) a)
data (+++@#@$$) (v1 :: Vec n a) :: (~>) (Vec m a) (Vec (n ++ m) a) where
(:+++@#@$$###) ::
(SameKind (Apply ((+++@#@$$) v1) arg) ((+++@#@$$$) v1 arg)) =>
(+++@#@$$) v1 v2
type instance Apply ((+++@#@$$) v1) v2 = (+++) v1 v2
instance SuppressUnusedWarnings ((+++@#@$$) v1) where
suppressUnusedWarnings = snd ((,) (:+++@#@$$###) ())
type (+++@#@$$$) :: Vec n a -> Vec m a -> Vec (n ++ m) a
type family (+++@#@$$$) (v1 :: Vec n a) (v2 :: Vec m a) :: Vec (n ++ m) a where
(+++@#@$$$) v1 v2 = (+++) v1 v2
type (+++) :: Vec n a -> Vec m a -> Vec (n ++ m) a
type family (+++) (a_abqp :: Vec n a) (a_abqq :: Vec m a) :: Vec (n ++ m) a where
(+++) 'VNil ys = ys
(+++) ('(:.) x xs) ys = Apply (Apply (:.@#@$) x) (Apply (Apply (+++@#@$) xs) ys)
(%+++) ::
( forall
(t1 :: Vec n a)
(t2 :: Vec m a).
Sing t1 ->
Sing t2 ->
Sing (Apply (Apply (+++@#@$) t1) t2 :: Vec (n m) a) ::
Type
)
(%+++) SVNil (sYs :: Sing ys) = sYs
(%+++) ((:%.) (sX :: Sing x) (sXs :: Sing xs)) (sYs :: Sing ys) =
applySing
(applySing (singFun2 @(:.@#@$) (:%.)) sX)
(applySing (applySing (singFun2 @(+++@#@$) (%+++)) sXs) sYs)
instance SingI ((+++@#@$) :: (~>) (Vec n a) ((~>) (Vec m a) (Vec (n ++ m) a))) where
sing = singFun2 @(+++@#@$) (%+++)
instance
(SingI v) =>
SingI ((+++@#@$$) (v :: Vec n a) :: (~>) (Vec m a) (Vec (n ++ m) a))
where
sing =
singFun1
@((+++@#@$$) (v :: Vec n a))
((%+++) (sing @v))
instance SingI1 ((+++@#@$$) :: Vec n a -> (~>) (Vec m a) (Vec (n ++ m) a)) where
liftSing (s :: Sing (v :: Vec n a)) =
singFun1
@((+++@#@$$) (v :: Vec n a))
((%+++) s)This feels like a fairly fundamental thing to want to do with singletons. Is there a standard way of getting round this problem?
Metadata
Metadata
Assignees
Labels
No labels