Specialization of linked polymorphic functions without embedding

Here is a minimal example reproducing the real problem I'm working on:

One library module:

module Lib where class H h where hash :: (S s)=> s -> h -> s class S s where mix :: s -> Int -> s instance (H x, H y)=> H (x,y) where hash s = \(x,y) -> s `hash` x `hash` y -- make this look "big": `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y `hash` x `hash` y instance H Int where hash s = \n -> s `mix` n 

Another, possibly user defined:

 module S where import Lib newtype Foo = Foo Int deriving Show instance S Foo where mix (Foo x) y = Foo (x+y) 

And our Main :

 module Main where import Lib import S import Criterion.Main main = defaultMain [ bench "foo" $ whnf (hash (Foo 1)) (2::Int,3::Int) ] 

Compiling with ghc 8.0.1 with ghc --make -Wall -O2 -rtsopts -ddump-to-file -ddump-simpl -dsuppress-module-prefixes -dsuppress-uniques -ddump-core-stats -ddump-inlinings -fforce-recomp Main.hs

In this test, above 4 μs . If, however, we put INLINE pragmas on two hash declarations in Lib , we will see the required specializations and get a 66 ns runtime.

But I really do not want to embed everything (in the real user Main she can call hash the same type many times), I just need a function specialized for each combination of H and S in the user code.

Changing INLINE pragmas to INLINABLE caused a regression of the old behavior (as I believe, since the GHC inlining heuristic is still in the game). Then I tried to add

 {-# SPECIALIZE hash :: H a=> Foo -> a -> Foo #-} 

for modules Main and S , but this generates

 Ignoring useless SPECIALISE pragma for class method selector 'hash' 

... warnings and the same bad code.

Some limitations:

  • It would be acceptable, although not ideal, to require that every instance declaration of S include a finite number of pragmas (possibly related to H )
  • similar for H
  • it is not acceptable to require users to do SPECIALIZE for each combination of S and H

Is it possible to do this without INLINE?

This is probably the same as the Restricted Specialization and the associated truck ticket https://ghc.haskell.org/trac/ghc/ticket/8668 , but I thought I would ask again and maybe post it as simpler example for GHC Trac.


EDIT : went ahead and opened a ghc ticket: https://ghc.haskell.org/trac/ghc/ticket/13376

+6
source share

Source: https://habr.com/ru/post/1015486/


All Articles