这是一个重复我正在处理的真正问题的最小例子:
一个库模块:
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 --make -Wall -O2 -rtsopts -ddump-to-file -ddump-simpl -dsuppress-module-prefixes -dsuppress-uniques -ddump-core-stats -ddump-inlinings -fforce-recomp Main.hs
使用INLINE
编译ghc 8.0.1。
上述基准测试以4μs运行。但是,如果我们在hash
中的两个Lib
声明中添加Main
个pragma,我们会看到我们想要的预期特化,并获得 66 ns 的运行时。
但我真的不想内联所有内容(在用户的真实hash
中,她可能在同一类型上多次调用H
),我只想要针对每种组合专门使用该功能用户代码中的S
和INLINE
实例
将INLINABLE
pragma更改为{-# SPECIALIZE hash :: H a=> Foo -> a -> Foo #-}
导致旧行为回归(我认为,因为GHC的内联启发式方法仍在发挥作用)。然后我尝试添加
Main
同时发送S
和Ignoring useless SPECIALISE pragma for class method selector ‘hash’
模块,但这会生成
S
...警告和相同的错误代码。
一些限制:
H
实例声明包含有限数量的pragma(可能与H
相关)SPECIALIZE
S
和H
的每个组合执行<html>
<head lang="en">
<meta charset="UTF-8">
</head>
<body>
<!-- language: PHP -->
<?php
if(isset($_POST['age'])) {
echo $_POST['age'];
}
?>
<h1>Fill in the form</h1>
<form method="POST" action="http://localhost/try/">
<p>age:</p>
<input type="text" name="age">
<input type="submit" name="submit">
</form>
是不可接受的。没有INLINE可以做到这一点吗?
这可能与Specialization with Constraints和相关的trac ticket https://ghc.haskell.org/trac/ghc/ticket/8668相同,但我想我会再次提出并可能将此作为GHC Trac的一个简单示例发布。
编辑:继续开通ghc门票:https://ghc.haskell.org/trac/ghc/ticket/13376