专门化没有内联的相关多态函数
以下是我正在处理的一个实际问题的最简单示例:
一个库模块:
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
另一种可能由用户定义:
module S where
import Lib
newtype Foo = Foo Int
deriving Show
instance S Foo where
mix (Foo x) y = Foo (x+y)
而我们的Main
:
module Main where
import Lib
import S
import Criterion.Main
main = defaultMain [
bench "foo" $ whnf (hash (Foo 1)) (2::Int,3::Int)
]
使用ghc编译ghc 8.0.1 ghc --make -Wall -O2 -rtsopts -ddump-to-file -ddump-simpl -dsuppress-module-prefixes -dsuppress-uniques -ddump-core-stats -ddump-inlinings -fforce-recomp Main.hs
上述基准测试运行时间为4μs 。 但是,如果我们将INLINE
hash
放在Lib
的两个hash
声明中,我们会看到期望的特化,并获得66 ns的运行时间。
但我并不真正想要内联一切(在用户真正的Main
她可能会在相同类型上多次调用hash
),我只是希望为用户代码中的每个H
和S
实例组合专门设置该函数。
将INLINE
INLINABLE
更改为INLINABLE
导致旧行为回归(预计我认为,因为GHC的内联启发式算法仍在发挥作用)。 然后我尝试添加
{-# SPECIALIZE hash :: H a=> Foo -> a -> Foo #-}
到Main
模块和S
模块,但这会产生
Ignoring useless SPECIALISE pragma for class method selector ‘hash’
...警告和相同的错误代码。
一些限制:
S
实例声明包含有限数量的编译指示(可能与H
有关) H
也是如此 S
和H
每个组合都进行SPECIALIZE
是不可接受的。 没有INLINE可以这样做吗?
这可能与具有约束的专业化和相关的trac ticket https://ghc.haskell.org/trac/ghc/ticket/8668相同,但我想我会再次提问,并可能将此作为更简单的示例发布到GHC Trac 。
编辑 :继续并打开ghc票:https://ghc.haskell.org/trac/ghc/ticket/13376
链接地址: http://www.djcxy.com/p/33197.html上一篇: Specializing related polymorphic functions without inlining