Haskell中的隐式模式匹配

时间:2017-03-05 18:16:00

标签: performance haskell pattern-matching

是否应该预测这两个empty之间的性能差异,还是仅仅是风格偏好的问题?

foo list = case list of
   []      -> True
   (_ : _) -> False

bar list = case list of
   (_ : _) -> False
   _       -> True

1 个答案:

答案 0 :(得分:12)

一般情况下,你不应该期望性能可以在琐碎的摆弄与你所询问的模式之间发生变化,并且通常可以预期生成的代码是相同的。

但实际检查的方法是使用标准来查看核心和/或基准。在这种情况下,生成的代码是相同的,实际上GHC似乎实际上将它们组合在一起:

我用

编译了上面的代码段
ghc -Wall -O2 -ddump-to-file -ddump-simpl -dsuppress-module-prefixes -dsuppress-uniques -fforce-recomp  YourCode.hs

我们看到了这个核心:

foo :: forall t. [t] -> Bool
[GblId,
 Arity=1,
 Caf=NoCafRefs,
 Str=DmdType <S,1*U>,
 Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
         WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False)
         Tmpl= \ (@ t) (list [Occ=Once!] :: [t]) ->
                 case list of _ [Occ=Dead] {
                   [] -> True;
                   : _ [Occ=Dead] _ [Occ=Dead] -> False
                 }}]
foo =
  \ (@ t) (list :: [t]) ->
    case list of _ [Occ=Dead] {
      [] -> True;
      : ds ds1 -> False
    }

-- RHS size: {terms: 1, types: 0, coercions: 0}
bar :: forall t. [t] -> Bool
[GblId,
 Arity=1,
 Caf=NoCafRefs,
 Str=DmdType <S,1*U>,
 Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
         WorkFree=True, Expandable=True,
         Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False)
         Tmpl= \ (@ t) (list [Occ=Once!] :: [t]) ->
                 case list of _ [Occ=Dead] {
                   [] -> True;
                   : _ [Occ=Dead] _ [Occ=Dead] -> False
                 }}]
bar = foo

我认为Tmpl内容是在其他模块中内联的原始实现,但我不确定。