我有一个模块,该模块收集和导出许多小功能,例如:

fromEither :: (MonadError e m) => Either e a -> m a
fromEither = either throwError return

要么
withError :: MonadError e m => (e -> e) -> m a -> m a
withError = flip catchError (throwError . f)

内联它们是一个好主意,因为在专门研究MonadError的特定实例后,很可能会优化掉许多代码。

GHC的文档说:



这是否意味着最有可能将此类函数视为具有INLINE编译指示(即,在接口(interface)文件中记录的未经优化的RHS)?还是我必须自己添加INLINE?添加它是否有任何改变(假设GHC认为它们“足够小”)?

我不介意GHC是否决定不内联我的某些函数,如果觉得它们过于昂贵,但总的来说,我希望对它们进行内联,而不会在各处添加INLINE污染我的源代码。

最佳答案

根据我的经验,如果可行的话,这些小的功能将自动跨模块边界内联。

您可以通过在生成的ghc --show-iface -File上运行.hi来检查GHC是否决定实现这一点。如果它像下面的示例中说的有关Unfolding的内容,则在使用此模块时,该函数可能会被内联:

$ ghc --show-iface /usr/lib/ghc/base-4.6.0.1/Data/Either.hi
Magic: Wanted 33214052,
       got    33214052
...
38da29044ff77a85b08cebca1fed11ad
  either :: forall a c b.
            (a -> c) -> (b -> c) -> Data.Either.Either a b -> c
    {- Arity: 3, HasNoCafRefs, Strictness: LLS,
       Unfolding: (\ @ a
                     @ c
                     @ b
                     f :: a -> c
                     ds :: b -> c
                     ds1 :: Data.Either.Either a b ->
                   case ds1 of wild {
                     Data.Either.Left x -> f x Data.Either.Right y -> ds y }) -}

07-24 09:45
查看更多