我有一个模块,该模块收集和导出许多小功能,例如:
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 }) -}