来自GHC 7.6的文档:
[Y]你通常甚至不需要一开始的专业语用。当编译一个模块M时,GHC的优化器(with-o)会自动考虑在M中声明的每个顶级重载函数,并针对在M中调用它的不同类型对其进行专门化。优化器还会考虑每个导入的内联重载函数,并针对在M中调用它的不同类型对其进行专门化。
和
import Data.Vector.Unboxed as U
import Foo
main =
let y = Bar $ Qux $ U.replicate 11221184 0 :: Foo (Qux Int)
(Bar (Qux ans)) = iterate (plus y) y !! 100
in putStr $ show $ foldl1' (*) ans
foo.hs:
module Foo (Qux(..), Foo(..), plus) where
import Data.Vector.Unboxed as U
newtype Qux r = Qux (Vector r)
-- GHC inlines `plus` if I remove the bangs or the Baz constructor
data Foo t = Bar !t
| Baz !t
instance (Num r, Unbox r) => Num (Qux r) where
{-# INLINABLE (+) #-}
(Qux x) + (Qux y) = Qux $ U.zipWith (+) x y
{-# INLINABLE plus #-}
plus :: (Num t) => (Foo t) -> (Foo t) -> (Foo t)
plus (Bar v1) (Bar v2) = Bar $ v1 + v2
GHC专门用于调用plus
,但在qux
num
实例中不专门用于调用(+)
,这会降低性能。
但是,一个显式的杂注
{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}
根据我的理解,这个问题的要点如下:
阿法克,答案是否定的,大部分是肯定的,但还有其他方法,没有。
假设F
是一个函数,其类型包括一个类型变量a
,该变量受类型类C a
约束。默认情况下,GHC将针对一个类型应用程序的F
专门化(将a
替换为T
)如果F
在(a)同一模块中的任何函数的源代码中用该类型应用程序调用,或者(b)如果F
标记为inlinable
,则从b
导入F
的任何其他模块。因此,自动专门化是不可传递的,它只涉及在A
的源代码中导入和调用的inlinable
函数。
在您的示例中,如果按以下方式重写num
实例:
instance (Num r, Unbox r) => Num (Qux r) where
(+) = quxAdd
quxAdd (Qux x) (Qux y) = Qux $ U.zipWith (+) x y
quxadd
不是由main
专门导入的。main
导入num(Qux Int)
的实例字典,该字典在(+)
的记录中包含quxadd
。但是,尽管导入了字典,但字典中使用的内容却没有。plus
不调用quxadd
,它使用为num t
实例字典中的(+)
记录存储的函数。编译器在调用站点(main
)中设置此字典。我有一些代码使用两种不同类型的颜色,每个通道8位和每个通道16位,每个都由一个结构表示。为了有效地重用我的代码,我有一个模板函数可以对它们进行一些渲染。因此,我希望有一个模板函数来获取我的颜色通道的最大值。 我最初的尝试是这样的。我只展示了8 bpc的专业化 这不会在Visual studio 2012中编译。我明白了 1个 对我来说,我觉得这应该行得通,但我一直找不到任何例子。在Speciali
文件有两个驱动程序:(运行时间为~3秒)和(运行时间为~83秒),当使用d专门化用-O3编译时。 其核心是:对于测试,加法代码被专用于s等上的向量,而对于则使用通用向量代码。在第10行,您可以看到GHC编写了的专用版本,而不是第167行的通用版本。专门化的规则在第225行。我相信这条规则应该会在270号线上开火。(调用,因此是应该专门化的地方。) 我的目标是通过专门化使与一样快。我找到了两种方法:
经典背包。 这里有一个转折:在这些物品中,我需要确保我有从不同类别中提取的特定数量(不是最高的,而是确切的数量)。 所以让我们假设我们有类别 null
还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案
考虑代码: 我用不同的编译器(通过编译器资源管理器)测试了代码。 如果Clang 7.0.0编译,而给出错误: :8:20:错误:没有与函数模板专用化“栏”匹配的函数模板 :7:26:注意:已忽略候选模板:无法将'void()'与'int()'匹配 Visual C同意(MSVC 19 2017 RTW): (8) :错误C2912:显式专门化“int Test::bar(void)”不是函数模板
我有一个通用算法,需要访问其模板类型的特征。有一个特征类可以专门用于提供这些特征。 在我的类中使用此算法时,我想将其与类中定义的私有类型一起使用。 然而,专门化只能发生在或全局范围内,而我的类是不可访问的。 是否有可能以某种方式专门化具有私有类型的模板,至少在可访问此类型的范围内? 也许可以将这个专门化声明为一个类?