[Haskell-cafe] Can this be made to fuse?

Joachim Breitner mail at joachim-breitner.de
Thu Sep 22 17:56:12 UTC 2022


Hi,

Am Sonntag, dem 11.09.2022 um 19:05 -0400 schrieb David Feuer:
> The template-haskell package has functions `tupE` and `tupP` for
> building tuple expressions and patterns, respectively, but nothing
> really similar for building tuple types. I came up with the version
> below the other day:
> 
> -- | Given a list of types, produce the type of a tuple of
> -- those types. This is analogous to 'tupE' and 'tupP'.
> --
> -- @
> -- tupT [[t|Int|], [t|Char|], [t|Bool]] = [t| (Int, Char, Bool) |]
> -- @
> tupT :: [Q Type] -> Q Type
> tupT ts = n `seq` res
>   where
>     -- We build the expression with a thunk inside that will be filled in with
>     -- the length of the list once that's been determined. This works
>     -- efficiently (in one pass) because TH.Type is rather lazy.
>     (res, n) = foldl' (\(acc, !k) ty -> ([t| $acc $ty |], k + 1))
>                       (tupleT n, 0)
>                       ts
> 
> I strongly suspect this is quite fast enough in practice, but it's a
> bit annoying that it won't participate in list fusion; tupT (map f xs)
> will (lazily) generate an intermediate list. I wasn't able to convince
> GHC to fuse it, short of a custom rewrite rule or two (tupT (build f)
> = ..., tupT (augment f r = ...). Does anyone know if it's possible?

Can you say why it would not fuse? It seems it could, if tupT inlines,
and then you have foldl' applied to (map f xs), and at this point I
would hope that fusion kicks in.

Cheers,
Joachim

-- 
Joachim Breitner
  mail at joachim-breitner.de
  http://www.joachim-breitner.de/



More information about the Haskell-Cafe mailing list