haskell-ja > Archives > 2010/08/15

2010/08/15 00:45:04 UTCshelarcy
#
++ 演算子周りの話を付け加えておきますね。
#
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
#
この辺の話について詳しく知りたい方は、やはり手前味噌ですがこちらの記事を参照してください。 http://itpro.nikkeibp.co.jp/article/COLUMN/20100302/345243/
#
なお、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
#
という話も昨日していたのですが、こちらには書いていなかったので念のため。