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

ÉRDI Gergő gergo at erdi.hu
Wed Jul 3 04:35:00 UTC 2024


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
>
>

-- 

   .--= ULLA! =-----------------.
    \     http://gergo.erdi.hu   \
     `---= gergo at erdi.hu =-------'


More information about the ghc-devs mailing list