标签: ghc

GHC中自动专业化的传递性

来自GHC 7.6 的文档:

[Y]你通常甚至不需要SPECIALIZE pragma.在编译模块M时,GHC的优化器(带-O)自动考虑在M中声明的每个顶级重载函数,并将其专门用于在M中调用它的不同类型.优化器还考虑每个导入的INLINABLE重载函数,并将其专门用于M中调用的不同类型.

此外,给定函数f的SPECIALIZE编译指示,GHC将自动为f调用的任何类型类重载函数创建特殊化,如果它们与SPECIALIZE编译指示位于同一模块中,或者它们是INLINABLE; 等等,过渡性的.

因此GHC应该自动专门化一些INLINABLE 没有编译指示标记的/大多数/所有(?)函数,如果我使用显式编译指示,则特化是可传递的.我的问题是:auto -specialization 是否具有传递性?

具体来说,这是一个小例子:

Main.hs:

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
Run Code Online (Sandbox Code Playgroud)

Foo.hs:

module Foo (Qux(..), Foo(..), plus) where

import Data.Vector.Unboxed as U

newtype Qux r = Qux (Vector r)
-- …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

391
推荐指数
1
解决办法
2万
查看次数

追踪约束的技巧

这是场景:我已经编写了一些带有类型签名的代码,并且GHC抱怨无法推断x~y某些xy.你通常可以将GHC作为一个骨骼并简单地将同构函数添加到函数约束中,但这有几个原因:

  1. 它并不强调理解代码.
  2. 你可以得到5个约束,其中一个就足够了(例如,如果5个被一个更具体的约束暗示)
  3. 如果你做错了什么或者GHC没有帮助,你最终可能会受到假的限制

我只花了几个小时与案例3作斗争.我正在玩syntactic-2.0,我试图定义一个与域无关的版本share,类似于在中定义的版本NanoFeldspar.hs.

我有这个:

{-# LANGUAGE GADTs, FlexibleContexts, TypeOperators #-}
import Data.Syntactic

-- Based on NanoFeldspar.hs
data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          Domain a ~ sup,
          Domain b ~ sup,
          SyntacticN (a -> (a -> b) -> b) fi) 
      => a -> (a -> b) -> a
share = sugarSym Let
Run Code Online (Sandbox Code Playgroud)

和GHC could not …

haskell constraints ghc

321
推荐指数
1
解决办法
1万
查看次数

Haskell/GHC中的`forall`关键字有什么作用?

我开始理解forall关键字如何在所谓的"存在类型"中使用,如下所示:

data ShowBox = forall s. Show s => SB s
Run Code Online (Sandbox Code Playgroud)

然而,这仅仅是如何forall使用的一个子集,我根本无法将其用于这样的事情:

runST :: forall a. (forall s. ST s a) -> a
Run Code Online (Sandbox Code Playgroud)

或解释为什么这些是不同的:

foo :: (forall a. a -> a) -> (Char, Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))
Run Code Online (Sandbox Code Playgroud)

或整个RankNTypes东西......

我倾向于选择清晰,无术语的英语而不是学术环境中常见的语言.我尝试阅读的大部分解释(我可以通过搜索引擎找到的解释)存在以下问题:

  1. 他们不完整.他们解释如何使用这个关键字(如"生存型")的一个组成部分这让我感到高兴,直到我读使用它在一个完全不同的方式代码(比如runST,foobar以上).
  2. 他们密集地充满了假设,我已经阅读了最新的离散数学分类,类别理论或抽象代数本周流行.(如果我再也没有读过"请参阅论文的任何细节",那就太早了.)
  3. 它们的编写方式经常将简单的概念转变为曲折的语法和语法.

所以...

关于实际问题.任何人都可以完全解释的forall清晰,简单的英语关键字(或者,如果它存在于某个地方,点到我已经错过了这样一个明确的解释),不承担我在行话悠久的数学家?


编辑添加:

下面有高质量的答案有两个突出的答案,但不幸的是我只能选择一个最好的答案. 诺曼的回答很详细的和有用的,解释的方式,表现出一定的理论基础的东西forall,并在同一时间向我展示了一些它的实际影响. yairchu的回答覆盖了其他人没有提到的范围(范围类型变量),并用代码和GHCi会话说明了所有概念.我愿意选择两者是最好的.不幸的是,我不能和上,俯瞰着两个答案后密切,我已经决定,yairchu的稍微挤掉了诺曼,因为说明性代码和附加的说明.这是一个有点不公平,但是,因为我真的需要这两个答案,了解这一点是一点forall没给我留下了恐惧的隐隐感觉,当我看到它在类型签名.

syntax haskell types ghc forall

295
推荐指数
7
解决办法
4万
查看次数

为什么Haskell(GHC)如此快速?

Haskell(使用GHC编译器)比你期望的要快很多.如果使用得当,它可以与低级语言保持密切联系.(Haskellers最喜欢的事情是尝试在C的5%范围内(或者甚至击败它,但这意味着你使用的是低效的C程序,因为GHC将Haskell编译为C).)我的问题是,为什么?

Haskell是声明性的,基于lambda演算.机器架构显然势在必行,粗略地基于图灵机.实际上,Haskell甚至没有具体的评估顺序.此外,您不必处理机器数据类型,而是始终生成代数数据类型.

最奇怪的是更高阶函数.你会认为动态创建函数并抛出它们会使程序变慢.但是使用更高阶函数实际上使Haskell更快.实际上,似乎要优化Haskell代码,你需要使它更优雅和抽象,而不是更像机器.如果Haskell的更高级功能没有改进,它们似乎甚至都不会影响它的性能.

很抱歉,如果这听起来不错,但这是我的问题:为什么Haskell(使用GHC编译)如此之快,考虑到它的抽象性质和与物理机器的差异?

注意:我说C和其他命令式语言有点类似于图灵机的原因(但不是Haskell类似于Lambda微积分)是因为在命令式语言中,你有一个有限数量的状态(也就是行号) ,以及磁带(ram),以便状态和当前磁带确定对磁带做什么.有关从图灵机到计算机的过渡,请参阅维基百科条目,图灵机等效项.

performance haskell lambda-calculus ghc higher-order-functions

223
推荐指数
3
解决办法
4万
查看次数

什么时候-XAllowAmbiguousTypes合适?

我最近发布了一个问题,关于句法2.0有关的定义share.我在GHC 7.6中有这个工作:

{-# LANGUAGE GADTs, TypeOperators, FlexibleContexts #-}

import Data.Syntactic
import Data.Syntactic.Sugar.BindingT

data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          sup ~ Domain b, sup ~ Domain a,
          Syntactic a, Syntactic b,
          Syntactic (a -> b),
          SyntacticN (a -> (a -> b) -> b) 
                     fi)
           => a -> (a -> b) -> b
share = sugarSym Let
Run Code Online (Sandbox Code Playgroud)

但是,GHC 7.8希望-XAllowAmbiguousTypes …

haskell ghc

212
推荐指数
1
解决办法
6070
查看次数

阅读GHC核心

核心是GHC的中间语言.阅读核心可以帮助您更好地了解您的计划的性能.有人问我关于阅读Core的文档或教程,但我找不到多少.

有哪些文档可供阅读GHC Core?

这是我到目前为止所发现的:

compiler-construction performance haskell ghc

190
推荐指数
3
解决办法
2万
查看次数

GHC可以实现哪些优化可靠?

GHC有很多可以执行的优化,但我不知道它们是什么,也不知道它们在多大程度上被执行的可能性.

我的问题是:我可以期望每次或几乎可以应用哪些转换?如果我查看将要经常执行(评估)的一段代码,我的第一个想法是"嗯,也许我应该优化它",在这种情况下,我的第二个想法是,"甚至不要考虑它, GHC得到了这个"?

我正在阅读文章Stream Fusion:从列表到流到没有任何东西,以及他们用于将列表处理重写为不同形式的技术,GHC的正常优化将可靠地优化为简单的循环对我来说是新颖的.如何判断自己的程序何时符合这种优化条件?

GHC手册中有一些信息,但它只是回答问题的一部分.

编辑:我正在开始赏金.我想要的是一个低级转换列表,如lambda/let/case-floating,类型/构造函数/函数参数特化,严格性分析和拆箱,worker/wrapper,以及我遗漏的任何其他重要的GHC做的事情,以及输入和输出代码的解释和示例,以及理想情况下总效应大于其各部分之和的情况.理想情况下,有些人提到何时不会发生转变.我不期待对每个转换的新颖长度的解释,一些句子和内联单行代码示例就足够了(或者链接,如果它不是20页的科学论文),只要大图是在它结束时清楚.我希望能够查看一段代码,并能够很好地猜测它是否会编译成紧密循环,或者为什么不编译,或者我需要改变它来制作它.(我对像流融合这样的大优化框架(我只是阅读了一篇关于它的论文)感兴趣;更多的是那些编写这些框架的人所拥有的知识.)

optimization haskell ghc

177
推荐指数
3
解决办法
8824
查看次数

约束专业化

我遇到了让GHC专门化一个具有类约束的函数的问题.我有我的问题就在这里的一个小例子:Foo.hsMain.hs.这两个文件编译(GHC 7.6.2,ghc -O3 Main)并运行.

注意: Foo.hs真的被剥离了.如果您想了解为什么需要约束,可以在这里看到更多代码.如果我将代码放在一个文件中或进行许多其他微小的更改,GHC只是简单地将调用内联到plusFastCyc.这不会发生在实际代码中,因为plusFastCycGHC内联太大,即使在标记时也是如此INLINE.关键是要专门调用plusFastCyc,而不是内联它.plusFastCyc在真实代码的许多地方被调用,所以即使我可以强迫GHC这样做,也不可能复制这么大的功能.

感兴趣的代码是plusFastCycin Foo.hs,在这里转载:

{-# INLINEABLE plusFastCyc #-}
{-# SPECIALIZE plusFastCyc :: 
         forall m . (Factored m Int) => 
              (FastCyc (VT U.Vector m) Int) -> 
                   (FastCyc (VT U.Vector m) Int) -> 
                        (FastCyc (VT U.Vector m) Int) #-}

-- Although the next specialization makes `fcTest` fast,
-- it isn't useful to me in …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

155
推荐指数
1
解决办法
5993
查看次数

为什么GHC这么大/大?

有一个简单的答案:为什么GHC这么大?

  • OCaml:2MB
  • Python:15MB
  • SBCL:9MB
  • OpenJRE - 26MB
  • GHC:113MB

对于"如果Haskell是正确的工具,为什么我不应该关心大小"的传福音不感兴趣; 这是一个技术问题.

haskell ghc

145
推荐指数
6
解决办法
2万
查看次数

GHC-mod是否必须使用类型的全名?

我正在尝试使用ghc-modvim插件进行类型/语法检查等.但是,我发现ghc-mod总是在错误消息中使用完整的类型路径,例如:

test.hs|71 col 13 error| Couldn't match type ‘Data.Text.Internal.Text’                                                                                   
||                with ‘[GHC.Types.Char]’
|| Expected type: containers-0.5.6.2:Data.Map.Base.Map
||                  [GHC.Types.Char]
||                  ([(integer-gmp-1.0.0.0:GHC.Integer.Type.Integer,
||                     integer-gmp-1.0.0.0:GHC.Integer.Type.Integer)],
||                   containers-0.5.6.2:Data.Set.Base.Set
||                     integer-gmp-1.0.0.0:GHC.Integer.Type.Integer)
||   Actual type: containers-0.5.6.2:Data.Map.Base.Map
||                  Data.Text.Internal.Text
||                  ([(integer-gmp-1.0.0.0:GHC.Integer.Type.Integer,
||                     integer-gmp-1.0.0.0:GHC.Integer.Type.Integer)],
||                   containers-0.5.6.2:Data.Set.Base.Set
||                     integer-gmp-1.0.0.0:GHC.Integer.Type.Integer)
|| In the second argument of ‘containers-0.5.6.2:Data.Map.Base.map’, namely
||   ‘zippedMap’
|| In the second argument of ‘(GHC.Base.$)’, namely
||   ‘containers-0.5.6.2:Data.Map.Base.map
...
Run Code Online (Sandbox Code Playgroud)

这会使屏幕变得杂乱,我很难找出哪里出了问题.作为比较,这是使用以下内容的同一文件的错误消息ghci:

test.hs:71:13:
    Couldn't match type ‘T.Text’ with ‘[Char]’
    Expected type: M.Map [Char] ([(Integer, …
Run Code Online (Sandbox Code Playgroud)

haskell ghc ghc-mod

143
推荐指数
1
解决办法
1629
查看次数