Haskell中{ - ## - }的目的

时间:2014-03-31 22:49:46

标签: haskell

我正在通过Haskell code看看我如何编写类似的流融合函数,我注意到一个有趣的语法结构,{ - #...# - },我没有遇到过;所以我想知道它是什么以及如何找到它是如何工作的:

-- | /O(n)/ Drop elements that do not satisfy the predicate
filter :: Vector v a => (a -> Bool) -> v a -> v a
{-# INLINE filter #-}
filter f = unstream . inplace (MStream.filter f) . stream

更具体地说,特定行做了什么?

{-# INLINE filter #-}

2 个答案:

答案 0 :(得分:11)

GHC有一个" pragma"系统允许您为GHC指定语言外信息。特别是,它们看起来像

{-# <NAME> <ARGS...> #-}

您将看到的最常见的是语言扩展编译指示,它必须位于文件的顶部,并影响对文件其余部分有效的语言扩展。

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Example where

通常情况下,忽略编译指示不应该影响程序的含义。对于像INLINE这样的pragma来说,这是大致正确的,因为它们只是提示编译器,无论在何处调用此函数的主体都应该内联,以便开辟新的优化机会。 Haskell语义为我们提供了关于何时这种内联转换不会改变程序含义的保证,因此编译器对内联是否对程序含义没有影响的选择(只要它不是这样)违反了这些保证的假设。)

LANGUAGE pragma有点不同,因为它们确切地指定了为文件的其余部分写入的语言。例如,我们通常假设基本语言为Haskell98Haskell2010LANGUAGE pragma添加扩展名,以便前面举例说明的文件的语言为

Haskell2010 + RankNTypes + FlexibleInstances + ScopedTypeVariables

但是除了暗示编译器正在编写哪种语言之外,这些编译指示没有其他意义。


完整的允许pragma集取决于所使用的编译器。 GHC's pragmas are listed here(请注意,此链接适用于版本7.6.3,而注释中的链接适用于7.0.3)。使用LANGUAGE以外的编译指示可能是粗略的和特定于平台的,因此请仔细了解它们的用法和含义。

例如,关于图书馆作者是否应该使用INLINE的争论很大,因为它往往暗示对GHC自己的内联启发式缺乏信心,因此我们应该花钱通过手动INLINE s更加努力收紧而不是乱扔垃圾的代码。但是,如果谨慎使用,INLINEINLINABLE会对紧密的内环产生深远的影响。

答案 1 :(得分:6)

这是 pragma 。它基本上是语言标准本身无法表达的东西,但仍然会说出与编译器相关的东西。

这些pragma中的一些基本上是可选的,例如提高性能,因此评论般的外观。在您的示例中,INLINE表示编译器应该努力不仅仅链接到相关函数,而实际上在其调用的任何地方“硬编码”它。这原则上不会改变程序语义,但会对性能和内存使用产生相当大的影响(特别是如果与额外的流融合等技术相结合)。