How to implement type-level list concatenation as a GHC primitive type family

Hécate hecate at glitchbra.in
Wed Jul 3 07:42:30 UTC 2024


Thank you Gergő, this delightfully cursed! :D

I was pointed by someone off-list to “Note [Adding built-in type 
families]” which is actually very complete!

One last thing is that since everything is Xi-typed (new form of 
"stringly-typed" uncovered), the meaning of the parameters is a bit 
blurred when they all are called x1, z1, y1, in GHC.Builtin.Types.Literals.

See for instance: 
https://hackage.haskell.org/package/ghc-9.10.1/docs/src/GHC.Builtin.Types.Literals.html#interactInertAppendSymbol

Le 03/07/2024 à 06:35, ÉRDI Gergő a écrit :
> I know this is not exactly what you're asking, but in similar 
> situations I've had very good results from implementing my type family 
> as a type checker plugin. Unfortunately it's not code that I can 
> share, but it roughly goes like this:
>
> 1. Declare a closed type family without defining any clauses:
>
>     type family Append (xs :: [k]) (ys :: [k]) :: [k] where
>
> 2. Create a typechecker plugin that in `tcPluginInit` looks up this 
> `Append` tyfam's tycon, and in `tcPluginRewrite` maps it to a 
> `TcPluginRewriter`
>
> 3. Inside the `TcPluginRewriter`, you have a `[TcType]` which are your 
> arguments (so the two type-level lists that are concatenated in your 
> example). If you can compute your tyfam result from that, you can then 
> return a `TcPluginRewriteTo` with the "trust-me" coercion `UnivCo`. 
> This is what really helps with performance vs. a native 
> Haskell-defined tyfam, since it avoids Core passing around huge 
> coercion terms corresponding to every reduction step. 
> (https://gitlab.haskell.org/ghc/ghc/-/issues/8095 
> https://gitlab.haskell.org/ghc/ghc/-/issues/22323 and many more)
>
> The only tricky part is that in step 3, you have to be prepared to 
> handle pratially meta arguments. For example, if your arguments are
> `String : Double : []` and `Int : Bool : α` (with some typechecker 
> metavariable `α`), you can of course reduce that to `String : Double : 
> Int : Bool : α`. But if they are flipped, you can either bail out 
> until `α` is solved, or make partial progress to `Int : Bool : Append 
> α (String : Double : [])`. I don't know which is the right choice in 
> general, since bailing out might expose less info to type inference, 
> but partial progressing means your coercion terms will grow, since 
> you're restoring some of that step-by-step representation.
>
> Let me know if any of this makes sense, I've got the flu atm so the 
> above might be too rambly :)
>
> Bye,
>     Gergo
>
> On Wed, 3 Jul 2024, Hécate via ghc-devs wrote:
>
>> Hi GHC devs,
>>
>> I was wondering recently, considering that type family evaluation is 
>> notoriously slow, how one would implement type-level list 
>> concatenation directly within GHC in a way that is much less 
>> expensive to run. So I am looking for pointers, as this part of GHC 
>> is fairly unknown to me.
>>
>> Thinking about it, I'm actually unsure where the tyfam evaluation is 
>> happening.
>>
>> Any advice would be appreciated.
>>
>> Cheers,
>> Hécate
>>
>>
>
-- 
Hécate ✨
🐦: @TechnoEmpress
IRC: Hecate
WWW: https://glitchbra.in
RUN: BSD



More information about the ghc-devs mailing list