Opened 8 months ago

Last modified 7 months ago

#16178 new feature request

Brackets and splices should be overloaded like the static keyword

Reported by: mpickering Owned by:
Priority: normal Milestone:
Component: Template Haskell Version: 8.6.3
Keywords: TypedTemplateHaskell Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

It's quite convenient that the static keyword is rebindable. To recap, if e :: T then static e :: (IsStatic p) => p t.

It should also be possible rebind brackets and splices in the same manner. So we introduce two type classes IsBracket and IsSplice. Now quoting a term e :: T has type e :: IsBracket p => p T and the argument to a splice must have type e :: IsSplice p => p T which results in a value of type T.

class IsBracket p where
  fromBracket :: Code t -> p t

class IsSplice p where
  toBracket :: p t -> Code t

foo :: IsBracket p => p Int
foo = [|| 5 ||]

qux :: (IsSplice p, IsBracket p) => Int
qux = $$(foo)

As an aside, arguably the static form should only be rebindable when RebindableSyntax is enabled but that boat seems to have sailed.

Change History (3)

comment:1 Changed 8 months ago by simonpj

Could you give some examples of how this new ability would be useful?

comment:2 Changed 8 months ago by mpickering

If you define a partially static monoid type such as the following which tries to evaluate as many concatenations statically as possible.

data PS a = Static a | Dynamic (Code a)

instance Monoid a => Monoid (PS a) where
   mempty = Static mempty
   (Static a) <> (Static b) = Static (a <> b)
   -- Using the overloading here
   a <> c = [|| $$a <> $$c ||]
   
lower :: Lift a => PS a -> Code a
lower (Static a) = lift a
lower (Dynamic c) = c

instance IsSplice PS where
  toBracket = lower

instance IsBracket PS where
  fromBracket = Dynamic

sta :: a -> PS a
sta = Static

Writing programs with this data type becomes much more pleasant as the additional lifting and lowering become transparent. You can combine together these layers multiple times to implicitly perform different rewritings but the client's splice will still end up looking the same.

prog = (sta () <> sta ()) <> [|| () ||]

comment:3 Changed 7 months ago by goldfire

This seems like something which should go through the normal proposals process...

Note: See TracTickets for help on using tickets.