#++ 演算子周りの話を付け加えておきますね。
#xs ++ ys ++ ... ++ zs という ++ 演算子だけの連なりは、融合変換されませんでした。
#test :: [Int] -> [Int] -> [Int] -> [Int]
test xs ys zs = xs ++ ys ++ zs
#$ghc -c -O2 MonadTest.hs -ddump-simpl
MonadTest.test =
\ (xs_ade :: [GHC.Types.Int])
(ys_adf :: [GHC.Types.Int])
(zs_adg :: [GHC.Types.Int]) ->
GHC.Base.++
@ GHC.Types.Int xs_ade (GHC.Base.++ @ GHC.Types.Int ys_adf zs_adg)
#xs、ys といったリスト(の生産者)が融合変換可能でないと、++ 規則で一度融合変換可能な形に変換された式が foldr/app 規則で元に戻ってしまうからのようですね。
#$ghc -c -O2 MonadTest.hs -ddump-simpl-stats
4 RuleFired
2 ++
2 foldr/app
#{-# RULES
"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
#-}
#"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys
##なお、xs、ys といったリスト(の生産者)が融合変換可能な場合には、++ 演算子を使ったリストの連結は融合変換されます、
#test' :: Int -> Int -> Int -> [Int]
test' x y z = take 4 (repeat x)
++ concat [[y],[y]]
++ zipWith (+) (repeat z) (replicate 5 z)
#$ ghc -c -O2 MonadTest.hs -ddump-simpl
MonadTest.test' =
\ (x_ade :: GHC.Types.Int)
(y_adf :: GHC.Types.Int)
(z_adg :: GHC.Types.Int) ->
let {
a_sln [ALWAYS Just L] :: [GHC.Types.Int]
LclId
[Str: DmdType]
a_sln =
letrec {
xs_sli :: [GHC.Types.Int] -> [GHC.Types.Int]
LclId
[Arity 1
Str: DmdType S]
xs_sli =
\ (ds_akU :: [GHC.Types.Int]) ->
case ds_akU of _ {
[] -> GHC.Types.[] @ GHC.Types.Int;
: y1_akZ ys_al0 ->
GHC.Types.:
@ GHC.Types.Int (GHC.Base.plusInt z_adg y1_akZ) (xs_sli ys_al0)
}; } in
let {
lvl_slv :: [GHC.Types.Int]
LclId
[]
lvl_slv =
GHC.Types.:
@ GHC.Types.Int z_adg (GHC.Types.[] @ GHC.Types.Int) } in
letrec {
xs1_slk :: GHC.Prim.Int# -> [GHC.Types.Int]
LclId
[Arity 1
Str: DmdType L]
xs1_slk =
\ (m_ajs :: GHC.Prim.Int#) ->
case GHC.Prim.<=# m_ajs 1 of _ {
GHC.Bool.False ->
GHC.Types.: @ GHC.Types.Int z_adg (xs1_slk (GHC.Prim.-# m_ajs 1));
GHC.Bool.True -> lvl_slv
}; } in
xs_sli (xs1_slk 5) } in
let {
a1_slp :: [GHC.Types.Int]
LclId
[Str: DmdType]
a1_slp = GHC.Types.: @ GHC.Types.Int y_adf a_sln } in
let {
n_slr :: [GHC.Types.Int]
LclId
[Str: DmdType]
n_slr = GHC.Types.: @ GHC.Types.Int y_adf a1_slp } in
let {
lvl_slw :: [GHC.Types.Int]
LclId
[]
lvl_slw = GHC.Types.: @ GHC.Types.Int x_ade n_slr } in
letrec {
xs_slt :: GHC.Prim.Int# -> [GHC.Types.Int]
LclId
[Arity 1
Str: DmdType L]
xs_slt =
\ (m_ajs :: GHC.Prim.Int#) ->
case GHC.Prim.<=# m_ajs 1 of _ {
GHC.Bool.False ->
GHC.Types.: @ GHC.Types.Int x_ade (xs_slt (G
#という話も昨日していたのですが、こちらには書いていなかったので念のため。