Skip to content

Allow static compilation of Arrays in a fashion similar to lists.

Motivation

The situation for lists

Currently if we write a top level static list like foo = [1,2,3,4] :: [Int]
the individual cons cells (and values) are floated out.

-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
foo7
foo7 = I# 1#

...

-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
foo3
foo3 = : foo4 []

-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0}
foo2
foo2 = : foo5 foo3

...

This is good! The whole list is fully evaluated at compile time and ends up as a bunch of static data in the executable.

.section .data

.globl M_foo3_closure
M_foo3_closure:
        .quad   ghczmprim_GHCziTypes_ZC_con_info
        .quad   M_foo4_closure+1
        .quad   ghczmprim_GHCziTypes_ZMZN_closure+1
        .quad   3

...

.globl M_foo_closure
M_foo_closure:
        .quad   ghczmprim_GHCziTypes_ZC_con_info
        .quad   M_foo7_closure+1
        .quad   M_foo1_closure+2
        .quad   3

Arrays

In any array backed data structure however, if we write "foo = fromList [1,2,3,4] :: Vector Int" we either end up with the fully evaluated list in the executable or excessive amounts of code. Either way it leads to work and allocations being performed which should be done at compile time.

For example this is additional code on top of the list for fromList [1,2,3,4] :: Vector Int at -O2

Click to show core output
Rec {
-- RHS size: {terms: 196, types: 205, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop2
foo_$s$wfoldlM_loop2
  = \ sc_s4n0
      sc1_s4mX
      sc2_s4mY
      sc3_s4mW
      sc4_s4mV
      sc5_s4mU
      sc6_s4mT ->
      let {
        y_a3mD
        y_a3mD = +# sc3_s4mW 1# } in
      case <# sc5_s4mU y_a3mD of {
        __DEFAULT ->
          case writeArray#
                 (sc4_s4mV `cast` <Co:5>)
                 (+# sc6_s4mT sc3_s4mW)
                 (I# sc1_s4mX)
                 (sc_s4n0 `cast` <Co:4>)
          of s'#_a3Wh
          { __DEFAULT ->
          foo_$s$wfoldlM_loop3
            (s'#_a3Wh `cast` <Co:3>) sc2_s4mY y_a3mD sc4_s4mV sc5_s4mU sc6_s4mT
          };
        1# ->
          case <=# sc5_s4mU 1# of {
            __DEFAULT ->
              let {
                y2_a3mN
                y2_a3mN = -# y_a3mD sc5_s4mU } in
              case <=# sc5_s4mU y2_a3mN of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = *# 2# sc5_s4mU } in
                  case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop3
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4mY
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc5_s4mU y2_a3mN } in
                  case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop3
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4mY
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              };
            1# ->
              let {
                y2_a3mT
                y2_a3mT = -# y_a3mD sc5_s4mU } in
              case <=# 1# y2_a3mT of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc5_s4mU 1# } in
                  case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop3
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4mY
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc5_s4mU y2_a3mT } in
                  case newArray# n#_a3TR uninitialised (sc_s4n0 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc4_s4mV `cast` <Co:5>) sc6_s4mT ipv1_a3TX 0# sc5_s4mU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc3_s4mW (I# sc1_s4mX) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop3
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4mY
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              }
          }
      }

-- RHS size: {terms: 202, types: 206, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop1
foo_$s$wfoldlM_loop1
  = \ sc_s4md
      sc1_s4m9
      sc2_s4ma
      sc3_s4mb
      sc4_s4m8
      sc5_s4m7
      sc6_s4m6
      sc7_s4m5 ->
      let {
        y_a3mD
        y_a3mD = +# sc4_s4m8 1# } in
      case <# sc6_s4m6 y_a3mD of {
        __DEFAULT ->
          case writeArray#
                 (sc5_s4m7 `cast` <Co:5>)
                 (+# sc7_s4m5 sc4_s4m8)
                 (I# sc1_s4m9)
                 (sc_s4md `cast` <Co:4>)
          of s'#_a3Wh
          { __DEFAULT ->
          foo_$s$wfoldlM_loop2
            (s'#_a3Wh `cast` <Co:3>)
            sc2_s4ma
            sc3_s4mb
            y_a3mD
            sc5_s4m7
            sc6_s4m6
            sc7_s4m5
          };
        1# ->
          case <=# sc6_s4m6 1# of {
            __DEFAULT ->
              let {
                y2_a3mN
                y2_a3mN = -# y_a3mD sc6_s4m6 } in
              case <=# sc6_s4m6 y2_a3mN of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = *# 2# sc6_s4m6 } in
                  case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop2
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4ma
                    sc3_s4mb
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc6_s4m6 y2_a3mN } in
                  case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop2
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4ma
                    sc3_s4mb
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              };
            1# ->
              let {
                y2_a3mT
                y2_a3mT = -# y_a3mD sc6_s4m6 } in
              case <=# 1# y2_a3mT of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc6_s4m6 1# } in
                  case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop2
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4ma
                    sc3_s4mb
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc6_s4m6 y2_a3mT } in
                  case newArray# n#_a3TR uninitialised (sc_s4md `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc5_s4m7 `cast` <Co:5>) sc7_s4m5 ipv1_a3TX 0# sc6_s4m6 ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc4_s4m8 (I# sc1_s4m9) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop2
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4ma
                    sc3_s4mb
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              }
          }
      }

-- RHS size: {terms: 208, types: 207, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop
foo_$s$wfoldlM_loop
  = \ sc_s4m3
      sc1_s4lY
      sc2_s4lZ
      sc3_s4m0
      sc4_s4m1
      sc5_s4lX
      sc6_s4lW
      sc7_s4lU
      sc8_s4lT ->
      let {
        y_a3mD
        y_a3mD = +# sc5_s4lX 1# } in
      case <# sc7_s4lU y_a3mD of {
        __DEFAULT ->
          case writeArray#
                 (sc6_s4lW `cast` <Co:5>)
                 (+# sc8_s4lT sc5_s4lX)
                 (I# sc1_s4lY)
                 (sc_s4m3 `cast` <Co:4>)
          of s'#_a3Wh
          { __DEFAULT ->
          foo_$s$wfoldlM_loop1
            (s'#_a3Wh `cast` <Co:3>)
            sc2_s4lZ
            sc3_s4m0
            sc4_s4m1
            y_a3mD
            sc6_s4lW
            sc7_s4lU
            sc8_s4lT
          };
        1# ->
          case <=# sc7_s4lU 1# of {
            __DEFAULT ->
              let {
                y2_a3mN
                y2_a3mN = -# y_a3mD sc7_s4lU } in
              case <=# sc7_s4lU y2_a3mN of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = *# 2# sc7_s4lU } in
                  case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop1
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4lZ
                    sc3_s4m0
                    sc4_s4m1
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc7_s4lU y2_a3mN } in
                  case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop1
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4lZ
                    sc3_s4m0
                    sc4_s4m1
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              };
            1# ->
              let {
                y2_a3mT
                y2_a3mT = -# y_a3mD sc7_s4lU } in
              case <=# 1# y2_a3mT of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc7_s4lU 1# } in
                  case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop1
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4lZ
                    sc3_s4m0
                    sc4_s4m1
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc7_s4lU y2_a3mT } in
                  case newArray# n#_a3TR uninitialised (sc_s4m3 `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc6_s4lW `cast` <Co:5>) sc8_s4lT ipv1_a3TX 0# sc7_s4lU ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc5_s4lX (I# sc1_s4lY) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  foo_$s$wfoldlM_loop1
                    (s'#1_a3Wh `cast` <Co:3>)
                    sc2_s4lZ
                    sc3_s4m0
                    sc4_s4m1
                    y_a3mD
                    (ipv1_a3TX `cast` <Co:4>)
                    n#_a3TR
                    0#
                  }
                  }
                  }
              }
          }
      }

-- RHS size: {terms: 200, types: 209, coercions: 76, joins: 0/7}
foo_$s$wfoldlM_loop3
foo_$s$wfoldlM_loop3
  = \ sc_s4nI sc1_s4nG sc2_s4nF sc3_s4nE sc4_s4nD sc5_s4nC ->
      let {
        y_a3mD
        y_a3mD = +# sc2_s4nF 1# } in
      case <# sc4_s4nD y_a3mD of {
        __DEFAULT ->
          case writeArray#
                 (sc3_s4nE `cast` <Co:5>)
                 (+# sc5_s4nC sc2_s4nF)
                 (I# sc1_s4nG)
                 (sc_s4nI `cast` <Co:4>)
          of s'#_a3Wh
          { __DEFAULT ->
          $wfoldlM_loop_r4vW
            SPEC sc5_s4nC sc4_s4nD sc3_s4nE y_a3mD [] (s'#_a3Wh `cast` <Co:3>)
          };
        1# ->
          case <=# sc4_s4nD 1# of {
            __DEFAULT ->
              let {
                y2_a3mN
                y2_a3mN = -# y_a3mD sc4_s4nD } in
              case <=# sc4_s4nD y2_a3mN of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = *# 2# sc4_s4nD } in
                  case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  $wfoldlM_loop_r4vW
                    SPEC
                    0#
                    n#_a3TR
                    (ipv1_a3TX `cast` <Co:4>)
                    y_a3mD
                    []
                    (s'#1_a3Wh `cast` <Co:3>)
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc4_s4nD y2_a3mN } in
                  case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  $wfoldlM_loop_r4vW
                    SPEC
                    0#
                    n#_a3TR
                    (ipv1_a3TX `cast` <Co:4>)
                    y_a3mD
                    []
                    (s'#1_a3Wh `cast` <Co:3>)
                  }
                  }
                  }
              };
            1# ->
              let {
                y2_a3mT
                y2_a3mT = -# y_a3mD sc4_s4nD } in
              case <=# 1# y2_a3mT of {
                __DEFAULT ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc4_s4nD 1# } in
                  case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  $wfoldlM_loop_r4vW
                    SPEC
                    0#
                    n#_a3TR
                    (ipv1_a3TX `cast` <Co:4>)
                    y_a3mD
                    []
                    (s'#1_a3Wh `cast` <Co:3>)
                  }
                  }
                  };
                1# ->
                  let {
                    n#_a3TR
                    n#_a3TR = +# sc4_s4nD y2_a3mT } in
                  case newArray# n#_a3TR uninitialised (sc_s4nI `cast` <Co:4>) of
                  { (# ipv_a3TW, ipv1_a3TX #) ->
                  case copyMutableArray#
                         (sc3_s4nE `cast` <Co:5>) sc5_s4nC ipv1_a3TX 0# sc4_s4nD ipv_a3TW
                  of s'#_a3Uk
                  { __DEFAULT ->
                  case writeArray# ipv1_a3TX sc2_s4nF (I# sc1_s4nG) s'#_a3Uk
                  of s'#1_a3Wh
                  { __DEFAULT ->
                  $wfoldlM_loop_r4vW
                    SPEC
                    0#
                    n#_a3TR
                    (ipv1_a3TX `cast` <Co:4>)
                    y_a3mD
                    []
                    (s'#1_a3Wh `cast` <Co:3>)
                  }
                  }
                  }
              }
          }
      }

-- RHS size: {terms: 214, types: 242, coercions: 106, joins: 0/7}
$wfoldlM_loop_r4vW
$wfoldlM_loop_r4vW
  = \ w_s4aq ww_s4az ww1_s4aA ww2_s4aB ww3_s4aG w1_s4as w2_s4at ->
      case w_s4aq of { __DEFAULT ->
      case w1_s4as of {
        [] ->
          case unsafeFreezeArray#
                 (ww2_s4aB `cast` <Co:5>) (w2_s4at `cast` <Co:22>)
          of
          { (# ipv_a3yP, ipv1_a3yQ #) ->
          (# ipv_a3yP `cast` <Co:3>, Vector ww_s4az ww3_s4aG ipv1_a3yQ #)
          };
        : x_a3l6 xs1_a3l7 ->
          let {
            y_a3mD
            y_a3mD = +# ww3_s4aG 1# } in
          case <# ww1_s4aA y_a3mD of {
            __DEFAULT ->
              case writeArray#
                     (ww2_s4aB `cast` <Co:5>)
                     (+# ww_s4az ww3_s4aG)
                     x_a3l6
                     (w2_s4at `cast` <Co:4>)
              of s'#_a3Wh
              { __DEFAULT ->
              $wfoldlM_loop_r4vW
                SPEC
                ww_s4az
                ww1_s4aA
                ww2_s4aB
                y_a3mD
                xs1_a3l7
                (s'#_a3Wh `cast` <Co:3>)
              };
            1# ->
              case <=# ww1_s4aA 1# of {
                __DEFAULT ->
                  let {
                    y2_a3mN
                    y2_a3mN = -# y_a3mD ww1_s4aA } in
                  case <=# ww1_s4aA y2_a3mN of {
                    __DEFAULT ->
                      let {
                        n#_a3TR
                        n#_a3TR = *# 2# ww1_s4aA } in
                      case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
                      { (# ipv_a3TW, ipv1_a3TX #) ->
                      case copyMutableArray#
                             (ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
                      of s'#_a3Uk
                      { __DEFAULT ->
                      case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
                      { __DEFAULT ->
                      $wfoldlM_loop_r4vW
                        SPEC
                        0#
                        n#_a3TR
                        (ipv1_a3TX `cast` <Co:4>)
                        y_a3mD
                        xs1_a3l7
                        (s'#1_a3Wh `cast` <Co:3>)
                      }
                      }
                      };
                    1# ->
                      let {
                        n#_a3TR
                        n#_a3TR = +# ww1_s4aA y2_a3mN } in
                      case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
                      { (# ipv_a3TW, ipv1_a3TX #) ->
                      case copyMutableArray#
                             (ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
                      of s'#_a3Uk
                      { __DEFAULT ->
                      case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
                      { __DEFAULT ->
                      $wfoldlM_loop_r4vW
                        SPEC
                        0#
                        n#_a3TR
                        (ipv1_a3TX `cast` <Co:4>)
                        y_a3mD
                        xs1_a3l7
                        (s'#1_a3Wh `cast` <Co:3>)
                      }
                      }
                      }
                  };
                1# ->
                  let {
                    y2_a3mT
                    y2_a3mT = -# y_a3mD ww1_s4aA } in
                  case <=# 1# y2_a3mT of {
                    __DEFAULT ->
                      let {
                        n#_a3TR
                        n#_a3TR = +# ww1_s4aA 1# } in
                      case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
                      { (# ipv_a3TW, ipv1_a3TX #) ->
                      case copyMutableArray#
                             (ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
                      of s'#_a3Uk
                      { __DEFAULT ->
                      case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
                      { __DEFAULT ->
                      $wfoldlM_loop_r4vW
                        SPEC
                        0#
                        n#_a3TR
                        (ipv1_a3TX `cast` <Co:4>)
                        y_a3mD
                        xs1_a3l7
                        (s'#1_a3Wh `cast` <Co:3>)
                      }
                      }
                      };
                    1# ->
                      let {
                        n#_a3TR
                        n#_a3TR = +# ww1_s4aA y2_a3mT } in
                      case newArray# n#_a3TR uninitialised (w2_s4at `cast` <Co:4>) of
                      { (# ipv_a3TW, ipv1_a3TX #) ->
                      case copyMutableArray#
                             (ww2_s4aB `cast` <Co:5>) ww_s4az ipv1_a3TX 0# ww1_s4aA ipv_a3TW
                      of s'#_a3Uk
                      { __DEFAULT ->
                      case writeArray# ipv1_a3TX ww3_s4aG x_a3l6 s'#_a3Uk of s'#1_a3Wh
                      { __DEFAULT ->
                      $wfoldlM_loop_r4vW
                        SPEC
                        0#
                        n#_a3TR
                        (ipv1_a3TX `cast` <Co:4>)
                        y_a3mD
                        xs1_a3l7
                        (s'#1_a3Wh `cast` <Co:3>)
                      }
                      }
                      }
                  }
              }
          }
      }
      }
end Rec }

-- RHS size: {terms: 17, types: 30, coercions: 95, joins: 0/0}
foo1
foo1
  = \ s1_a1VO ->
      case newArray# 0# uninitialised (s1_a1VO `cast` <Co:20>) of
      { (# ipv_a3B5, ipv1_a3B6 #) ->
      foo_$s$wfoldlM_loop
        (ipv_a3B5 `cast` <Co:22>)
        1#
        2#
        3#
        4#
        0#
        (ipv1_a3B6 `cast` <Co:53>)
        0#
        0#
      }

-- RHS size: {terms: 5, types: 33, coercions: 0, joins: 0/0}
foo
foo
  = case runRW# foo1 of { (# ipv1_a23t, ipv2_a23u #) -> ipv2_a23u }

It's quite excessive for generating what boils down to an Array of 4 elements known ahead of time.

Proposal

Ideally GHC would have something like these magic functions to instantiate statically known arrays at compile time.

mkStaticArray# :: [a] -> Array# a
mkSmallStaticArray# :: [a] -> SmallArray# a

Which when the list is static will simply allocate the Array in the .data section just like we do for lists.

In particular a static list would be any list for which we:

  • Can compile all elements to a pointer known at compile time.
  • Know the length ahead of time.

This is however fragile as weither or not a list is static could (and likely would) change often based on GHC versions and optimization flags used.

An alternative might be to have "best effort" functions instead.

newSmallStaticArray# :: Int# -> [a] -> State# d -> (#State# d, SmallMutableArray# d a#)

With the idea being that semantically it's equal to fromListN but any static elements will be preallocated. So if the whole list is static we will not have any compile time allocation at all, but code would not randomly fail to compile.

I do not have a concrete implementation plan. I'm sure there are also hurdles to overcome I didn't even think of. But the current situation is unsatisfying.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information