- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
举个例子,假设我想在列表上编写一个单子(monad)和非单子(monad)映射。我将从一元的开始:
import Control.Monad
import Control.Monad.Identity
mapM' :: (Monad m) => (a -> m b) -> ([a] -> m [b])
mapM' _ [] = return []
mapM' f (x:xs) = liftM2 (:) (f x) (mapM f xs)
现在我想重用代码来编写纯 map
(而不是重复代码):
map' :: (a -> b) -> ([a] -> [b])
map' f = runIdentity . mapM' (Identity . f)
要使map'
像 written explicitly like map
is 一样优化,需要什么? ?特别是:
有必要写
{-# SPECIALIZE mapM' :: (a -> Identity b) -> ([a] -> Identity [b]) #-}
或者 GHC 是否优化了 map'
本身(通过完全排除 Identity
)?
还需要添加其他内容(更多编译指示)吗?
map'
对于 map
显式编写的代码的优化程度?最佳答案
好吧,让我们问问编译器本身。
编译模块
module PMap where
import Control.Monad
import Control.Monad.Identity
mapM' :: (Monad m) => (a -> m b) -> ([a] -> m [b])
mapM' _ [] = return []
mapM' f (x:xs) = liftM2 (:) (f x) (mapM f xs)
map' :: (a -> b) -> ([a] -> [b])
map' f = runIdentity . mapM' (Identity . f)
与ghc -O2 -ddump-simpl -ddump-to-file PMap.hs
(ghc-7.6.1、7.4.2 产生相同的结果,除了唯一的名称)为 map'
生成以下核心
PMap.map'
:: forall a_afB b_afC. (a_afB -> b_afC) -> [a_afB] -> [b_afC]
[GblId,
Arity=2,
Caf=NoCafRefs,
Str=DmdType LS,
Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=2, Value=True,
ConLike=True, WorkFree=True, Expandable=True,
Guidance=IF_ARGS [60 30] 160 40}]
PMap.map' =
\ (@ a_c) (@ b_d) (f_afK :: a_c -> b_d) (eta_B1 :: [a_c]) ->
case eta_B1 of _ {
[] -> GHC.Types.[] @ b_d;
: x_afH xs_afI ->
GHC.Types.:
@ b_d
(f_afK x_afH)
(letrec {
go_ahZ [Occ=LoopBreaker]
:: [a_c] -> Data.Functor.Identity.Identity [b_d]
[LclId, Arity=1, Str=DmdType S]
go_ahZ =
\ (ds_ai0 :: [a_c]) ->
case ds_ai0 of _ {
[] ->
(GHC.Types.[] @ b_d)
`cast` (Sym <(Data.Functor.Identity.NTCo:Identity <[b_d]>)>
:: [b_d] ~# Data.Functor.Identity.Identity [b_d]);
: y_ai5 ys_ai6 ->
(GHC.Types.:
@ b_d
(f_afK y_ai5)
((go_ahZ ys_ai6)
`cast` (<Data.Functor.Identity.NTCo:Identity <[b_d]>>
:: Data.Functor.Identity.Identity [b_d] ~# [b_d])))
`cast` (Sym <(Data.Functor.Identity.NTCo:Identity <[b_d]>)>
:: [b_d] ~# Data.Functor.Identity.Identity [b_d])
}; } in
(go_ahZ xs_afI)
`cast` (<Data.Functor.Identity.NTCo:Identity <[b_d]>>
:: Data.Functor.Identity.Identity [b_d] ~# [b_d]))
}
是的,只有cast
s,没有真正的开销。你得到一个本地 worker go
其作用与 map
完全相同确实如此。
总结:你只需要-O2
,并且您可以通过查看核心 ( -ddump-simpl
) 来验证代码的优化程度,或者如果您可以阅读它,则可以查看生成的程序集 ( -ddump-asm
) 或 LLVM 位代码 -ddump-llvm
来验证代码的优化程度。 )。
详细说明一下可能会更好。关于
Is it necessary to write
{-# SPECIALIZE mapM' :: (a -> Identity b) -> ([a] -> Identity [b]) #-}
or does GHC optimize
map'
itself (by factoring out Identity completely)?
答案是,如果您在定义通用函数的同一模块中使用特化,那么通常您不需要 {-# SPECIALISE #-}
pragma,如果 GHC 看到任何好处,它就会自己创建特化。在上述模块中,GHC 创建了特化规则
"SPEC PMap.mapM' [Data.Functor.Identity.Identity]" [ALWAYS]
forall (@ a_abG)
(@ b_abH)
($dMonad_sdL :: GHC.Base.Monad Data.Functor.Identity.Identity).
PMap.mapM' @ Data.Functor.Identity.Identity
@ a_abG
@ b_abH
$dMonad_sdL
= PMap.mapM'_$smapM' @ a_abG @ b_abH
这也有利于 mapM'
的任何使用在Identity
定义模块外部的 monad(如果使用优化进行编译,并且 monad 会及时被识别为 Identity
以触发规则)。
但是,如果 GHC 不能很好地理解专门化的类型,它可能看不到任何好处并且不会专门化(我不太了解它是否会尝试 - 到目前为止我发现每次我看时都会有一个专业)。
如果你想确定的话,看看核心。
如果您需要在不同的模块中进行专门化,GHC 在编译定义模块时没有理由专门化该函数,因此在这种情况下,需要使用编译指示。而不是{-# SPECIALISE #-}
pragma 要求对一些精心挑选的类型进行专门化,从 ghc-7 开始,使用 {-# INLINABLE #-}
可能会更好。 pragma,以便在导入模块中可以访问(稍作修改的)源代码,从而允许对那里的任何所需类型进行专门化。
Anything else (more pragmas) need to be added?
不同的用途当然可能需要不同的编译指示,但根据经验,{#- INLINABLE #-}
是你最想要的。当然还有{-# RULES #-}
可以实现编译器自身无法实现的魔法。
How can I verify how well the compiled
map'
is optimized wrt the explicitly written code formap
?
关于optimization - 如何正确使用GHC的SPECIALIZE pragma? (例如 : specializing pure function from monadic ones using Identity. ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12992481/
在我学习期间Typoclassopedia我遇到了这个证明,但我不确定我的证明是否正确。问题是: One might imagine a variant of the interchange law
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 已关闭 8 年前。 Improve
我的理解是,“纯 OCaml”是指 OCaml 中标准的所有内容,包括其非“纯”功能特性,而“纯功能”是指通常的属性:没有副作用、没有异常处理等。从这个意义上说,“纯 OCaml” 实现与使用 C 或
Haskell 被称为“纯函数式语言”。 在这种情况下“纯粹”是什么意思?这会给程序员带来什么后果? 最佳答案 在纯函数式语言中,您不能做任何有副作用的事情。 副作用意味着计算表达式会改变某些内部状态
这是接口(interface)契约类的一部分。 [Pure] public bool IsDirty() { throw new NotImplementedException(); } pu
我想问一下 pure-g 和 pure-g-r 有什么区别。我曾经认为响应式会让我的 div 在较低的分辨率下不会崩溃但是使用 pure-g 也帮助我实现了同样的效果,所以我对它们之间的正确区别感到困
在source code of GHC.Base , Applicative Maybe 定义为: instance Applicative Maybe where pure = Just
这个问题在这里已经有了答案: Purpose of (0, obj.method)(param1, param2) in Closure Compiler minified code (1 个回答)
如何向 React 发出信号,表明函数组件是“纯”的,相当于组件类的 React.PureComponent ? function C(props) { return {props.n} } 没有
已阅读官方React documentation ,我遇到过this关于PureComponent: Furthermore, React.PureComponent’s shouldComponen
我有以下代码片段,我想知道它是纯 C 还是包含一些 C++ 元素。这个问题源于我认为它只是 C,但有些编译器不接受代码。 // User struct derived from Function
一个简单的问题。我应该如何在数据库中存储电话号码和电子邮件地址?只是像 email@email.com 这样的纯文本(或数字),还是用 key 对其进行编码更好(有点像密码在数据库中的保存方式)。在那
有人可以向我展示一个示例,说明我如何使用 purecss.io 来实现固定宽度/响应式设计,类似于 bootstrap 等 960 网格???? 流体宽度根本不适用于我的特定设计,这是我目前拥有的:
是否有一套通用规则/指南可以帮助您了解何时更喜欢pragma Pure,pragma Preelaborate或其他什么东西? standard (Ada 2012)中提供的规则和定义有些繁琐,我很高
我试图区分包含字母字符数据的单元格和数字数据单元格。我使用 istext() 和 isnumber() 取得了部分成功。但是当出现字母数字字符时,这种逻辑就会失败。 我的目的是检测只有字母的单元格。包
在Clash官方网站上,有以下示例: >>> sampleN @System 4 (register 0 (pure (8 :: Signed 8))) 我知道什么是纯函数,但为什么这里有 this
据我了解,javascript 要么在浏览器中运行,要么作为 Node.js 中的后端运行。 浏览器或 Node.js,根据您运行 JavaScript 的位置,将通过 Web API 或 C++ A
class Applicative f => Monad f where return :: a -> f a (>>=) :: f a -> (a -> f b) ->
在我看来,Fortran 中所谓的纯函数对于那些使用函数式编程的人来说似乎不够纯粹。这是我的问题。假设我有以下代码: MODULE basics IMPLICIT NONE INTEGER,
在Clash官方网站上,有以下示例: >>> sampleN @System 4 (register 0 (pure (8 :: Signed 8))) 我知道什么是纯函数,但为什么这里有 this
我是一名优秀的程序员,十分优秀!