Haskell has a [`maximum`](http://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:maximum) function and it has lazy evaluations of lists. I come from Python that has a `max` function and list generators. But there turns out to be a crucial difference. [Day 11](https://adventofcode.com/2018/day/11) asks us to find maximum-value squares in a programatically defined integer array. Part 1 asks for 3x3 squares so I (foolishly) built something that only worked for 3x3 squares. Puzzle input is a "serial number" so I made a function that when partially applied to the serial number gives the function x, y -> value of the cell. ``` type LevelFunction = Int -> Int -> Int fuelCellLevel :: Int -> LevelFunction fuelCellLevel serialNumber y x = let rackId = (x+10) allDigits = (rackId * y + serialNumber) * rackId in ((allDigits `div` 100) `mod` 10) - 5 ``` I felt the key here was going to be avoiding redundant calls to this function, as well as adding the same numbers over and over again. My solution for part 1 was to add three rows together: ``` 1 2 3 4 5 ... 6 7 8 9 10 ... 11 12 13 14 15 ... ------------------- 18 21 24 27 30 ... ``` and then take units of three to get the sum of all the 3x3 squares. In order to keep track of where the square came from, we need to have both a sum and a label. Generate an entire row of values: ``` gridRange = [1..300] rowLevels fn y = (map (fn y) gridRange) ``` Some utility functions for operating on tuples: ``` sum3 (a,b,c) = a + b + c sumColumns (y,as,bs,cs) = (y, map sum3 (zip3 as bs cs)) sumSquare y (x,a,b,c) = (a+b+c, x, y) ``` Take the rows three at a time and add them up in the way shown above. The `zip` functions all use the shortest list length. Using `zip` this way is a common Python idiom, I don't know if Haskell people do it too or if they have a different preferred way of accomplishing it. ``` threeByThreeLevels :: (Int -> Int -> Int) -> [(Int,Int,Int)] threeByThreeLevels fn = let rows = [ rowLevels fn y | y <- gridRange ] :: [[Int]] threeRows = zip4 gridRange rows (drop 1 rows) (drop 2 rows) :: [(Int,[Int],[Int],[Int])] threeRowsSummed = map sumColumns threeRows in concat (map sumSquares threeRowsSummed) ``` Then the same pattern is used to take the columns three at a time: ``` sumSquares :: (Int,[Int]) -> [(Int,Int,Int)] sumSquares (y,cols) = let threeCols = zip4 gridRange cols (drop 1 cols) (drop 2 cols) in map (sumSquare y) threeCols ``` We ordered things so that the sum comes first in the tuple, so we can just apply maximum to the tuples as they are: ``` maxSquare serialNumber = maximum (threeByThreeLevels (fuelCellLevel serialNumber)) ``` OK, that works for part 1. Part 2 asks us to find the maximum-valued square of any size, so all that work was wasted. I thought about it a bit and decided the right solution was inclusion/exclusion. Suppose we know, for every point `(m,n)` in the array, the value of the sum of all the entries between `(1,1)` and `(m,n)`. Then we can calculate the value of any smaller rectangle by doing some math.  We want the area of a small blue square not beginning at (1,1). So, we can start with the big sum (white square), subtract off the portion on the right that we don't want (red rectangle) and the portion on the bottom that we don't want (green rectangle.) That means part of the original area got subtracted twice, so we have to add that back in (yellow.) This technique allows us to precompute a matrix of all the area sums that start at (1,1), and then compute any other sum with just four references into this array. The code I wrote is a little magical, but follows one of the examples given in [Data.Array](http://hackage.haskell.org/package/array-0.5.3.0/docs/Data-Array.html). We can refer back to the array in order to define it! Here I do this twice, once to define columns in terms of earlier columns (and the previous row), and once to define the rows of the matrix in terms of its earlier rows: ``` -- Return an entire row's worth of sums rowPartialSums :: LevelFunction -> Int -> Array Int Int -> Array Int Int rowPartialSums fn y prevRow = let a = array (1,300) ((1, (prevRow!1) + fn y 1) : [(x, (a!(x-1)) + (prevRow!x) + (fn y x) - (prevRow!(x-1))) | x <- [2..300] ]) in a -- Entire matrix of sums, (array ! y) ! x = sum from (1,1) to (y,x) partialSums :: LevelFunction -> Array Int (Array Int Int) partialSums fn = let zero = array (1,300) [(x,0) | x <- [1..300]] rows = array (1,300) ((1, rowPartialSums fn 1 zero) : [(y, rowPartialSums fn y (rows!(y-1))) | y <- [2..300] ]) in rows sums serialNumber = partialSums (fuelCellLevel serialNumber) ``` If you look at `rowPartialSums` it's doing inclusion-exclusion here too. We want to define `A[x][y]` in terms of sums we already know. So it's equal to `fn(x,y) + A[x-1][y] + A[x][y-1]`, but both those values already include the value of `A[x-1][y-1]`. I see looking at this that I could have curried `fn` which was my intention for putting `y` first, but I didn't. Now to do the inclusion-exclusion, we need to be careful of the edge cases, so I just wrote everything out in four big cases and didn't worry too much about making it compact: ``` areaSum :: Array Int (Array Int Int) -> Int -> Int -> Int -> Int areaSum a 1 1 size = let x' = size y' = size in (a ! y') ! x' areaSum a 1 x size = let x' = x + size - 1 y' = size in (a ! y') ! x' - (a ! y') ! (x-1) areaSum a y 1 size = let x' = size y' = y + size - 1 in (a ! y') ! x' - (a ! (y-1)) ! x' areaSum a y x size = let x' = x + size - 1 y' = y + size - 1 in (a ! y') ! x' - (a ! (y-1)) ! x' - (a ! y') ! (x-1) + (a ! (y-1)) ! (x-1) ``` OK, just one more step and we're done, right? We just have to iterate over all sizes and all locations where squares of that sizes could fit, which we can do in one big list comprehension: ``` maxSquareK :: Int -> (Int,Int,Int,Int) maxSquareK sn = let a = sums sn in maximum [ (areaSum a y x size, x, y, size) | size <- [1..300], x <- [1..301-size], y <- [1..301-size] ] ``` Oops, doesn't work: `day11.hs: stack overflow` OK, time to try profiling. We can compile the program with profiling enabled like this: ``` mark@ubuntu:~/aoc2018/day11$ stack ghc -- -prof -fprof-auto -fprof-cafs day11.hs [1 of 1] Compiling Main ( day11.hs, day11.o ) Linking day11 ... ``` And run it like this to get heap profiling: ``` mark@ubuntu:~/aoc2018/day11$ ./day11 +RTS -hc -p ``` This results in a test file full of samples like this one: ``` BEGIN_SAMPLE 0.919256 (150)GHC.IO.Handle.Text.CAF 24 (241)CAF:$dShow_r3Z2 152 (126)PINNED 36816 (249)main 120 (248)main/CAF:main 96 MAIN 160 (233)GHC.Conc.Signal.CAF 640 (212)GHC.IO.Handle.FD.CAF 704 (220)GHC.IO.Encoding.Iconv.CAF 120 (222)GHC.IO.Encoding.CAF 1096 (277)maxSquareK/main/CAF:main 301482248 END_SAMPLE 0.919256 ``` OK, that's a lot of memory allocation, but why? ``` individual inherited COST CENTRE MODULE SRC no. entries %time %alloc %time %alloc ... maxSquareK Main day11.hs:(91,1)-(95,32) 277 1 41.1 47.3 81.2 70.4 areaSum Main day11.hs:(66,1)-(84,75) 278 967107 30.8 18.7 36.6 21.1 areaSum.y' Main day11.hs:83:3-19 295 960306 2.8 1.2 2.8 1.2 areaSum.x' Main day11.hs:82:3-19 296 960305 3.0 1.2 3.0 1.2 areaSum.x' Main day11.hs:77:3-11 286 3522 0.0 0.0 0.0 0.0 areaSum.y' Main day11.hs:78:3-19 283 3522 0.0 0.0 0.0 0.0 areaSum.x' Main day11.hs:72:3-19 294 3267 0.0 0.0 0.0 0.0 areaSum.y' Main day11.hs:73:3-11 293 3267 0.0 0.0 0.0 0.0 areaSum.x' Main day11.hs:67:3-11 292 12 0.0 0.0 0.0 0.0 areaSum.y' Main day11.hs:68:3-11 291 12 0.0 0.0 0.0 0.0 ``` I find this a little confusing; it looks like we're accumulating a lot of memory in `areaSum`. Actually, we're accumulating a bunch of unevaluated `areaSum` thunks. The reason is that `maximum` doesn't do what I thought, which is to do a strict fold. Instead it does lazy evaluation of the entire list of comparisons, as if the intermediate result was ``` max( a, max( b, max( c, max( d, ... ) ) ) ) ``` where each of the arguments is one of the `areaSum` function calls. I have no idea why this is the preferred default behavior. It also suggests that part 1 is using way too much memory as well. If you plot it memory usage does start going down, eventually, when we reach the end of the large list generated by the comprehension.  OK, quick hack. We'll use `foldl'` which uses strict evaluation (doesn't defer the comparison) like this: ``` maximum' = foldl' max (0,0,0,0) maxSquareK :: Int -> (Int,Int,Int,Int) maxSquareK sn = let a = sums sn in maximum' [ (areaSum a y x size, x, y, size) | size <- [1..300], x <- [1..301-size], y <- [1..301-size] ] ``` That works fine; it churns away a bit with high CPU but memory usage is modest. Full code: https://github.com/mgritter/aoc2018/blob/master/day11/day11.hs
author | markgritter |
---|---|
permlink | advent-of-code-day-11-spoilers-inclusion-exclusion-and-haskell-s-odd-design-decisions |
category | adventofcode |
json_metadata | {"tags":["adventofcode","programming","haskell","functionalprogramming","puzzle"],"image":["https://cdn.steemitimages.com/DQmdFKh9fmeJjvzaKRHmVEAAvFmjkNi4fJ9dk3SrKpfM3qo/inclusion-exclusion-areas.png","https://cdn.steemitimages.com/DQmQMef7iqBswdXPhnrLBB8eLY5qEWTy3aqGbN9R7wwdU8y/image.png"],"links":["http://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:maximum","https://adventofcode.com/2018/day/11","http://hackage.haskell.org/package/array-0.5.3.0/docs/Data-Array.html","https://github.com/mgritter/aoc2018/blob/master/day11/day11.hs"],"app":"steemit/0.1","format":"markdown"} |
created | 2019-01-04 04:39:30 |
last_update | 2019-01-04 04:39:30 |
depth | 0 |
children | 2 |
last_payout | 2019-01-11 04:39:30 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 1.546 HBD |
curator_payout_value | 0.472 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 10,190 |
author_reputation | 7,057,249,855,552 |
root_title | "Advent of Code Day 11 [spoilers], Inclusion-Exclusion, and Haskell's odd design decisions" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 77,844,403 |
net_rshares | 3,760,677,973,619 |
author_curate_reward | "" |
voter | weight | wgt% | rshares | pct | time |
---|---|---|---|---|---|
wackou | 0 | 18,702,679,453 | 0.32% | ||
lafona-miner | 0 | 193,217,612,262 | 5% | ||
eric-boucher | 0 | 1,831,145,216 | 0.54% | ||
anwenbaumeister | 0 | 15,620,062 | 1.08% | ||
lukestokes | 0 | 1,676,944,779,271 | 100% | ||
mammasitta | 0 | 273,372,166 | 0.05% | ||
liberosist | 0 | 1,905,654,822 | 1.08% | ||
cmp2020 | 0 | 18,809,516,714 | 35% | ||
minnowsunite | 0 | 199,797,171 | 100% | ||
lemouth | 0 | 24,050,633,334 | 5% | ||
rwilday | 0 | 55,323,763 | 100% | ||
lamouthe | 0 | 2,555,958,193 | 5% | ||
lk666 | 0 | 100,859,043 | 0.54% | ||
eforucom | 0 | 21,853,114,126 | 1% | ||
remlaps1 | 0 | 24,058,883,190 | 35% | ||
curie | 0 | 30,359,503,702 | 1.08% | ||
cub1 | 0 | 94,411,767,849 | 35% | ||
hendrikdegrote | 0 | 339,575,712,751 | 1.08% | ||
vact | 0 | 21,757,708,787 | 1.08% | ||
golbang | 0 | 2,386,470,322 | 0.32% | ||
steemstem | 0 | 228,758,749,647 | 5% | ||
remlaps2 | 0 | 2,156,776,393 | 35% | ||
dna-replication | 0 | 1,353,422,112 | 5% | ||
lisa.palmer | 0 | 2,320,883,799 | 35% | ||
cub2 | 0 | 2,126,327,483 | 35% | ||
astronomyizfun | 0 | 1,804,301,023 | 35% | ||
moksamol | 0 | 115,367,091 | 0.54% | ||
bloom | 0 | 13,644,008,865 | 4% | ||
epicdesigns | 0 | 2,070,682,827 | 10% | ||
iansart | 0 | 609,780,360 | 0.54% | ||
kryzsec | 0 | 1,169,261,270 | 4% | ||
jiujitsu | 0 | 173,951,800 | 0.54% | ||
helo | 0 | 3,417,605,693 | 2.5% | ||
samminator | 0 | 1,458,071,819 | 2.5% | ||
locikll | 0 | 452,506,932 | 2.16% | ||
mahdiyari | 0 | 3,778,117,493 | 2.5% | ||
lorenzor | 0 | 5,303,298,272 | 50% | ||
aboutyourbiz | 0 | 185,947,208 | 1.08% | ||
alexander.alexis | 0 | 2,217,168,428 | 5% | ||
suesa | 0 | 125,963,898,605 | 25% | ||
cryptokrieg | 0 | 91,823,403 | 1.08% | ||
corsica | 0 | 2,296,984,470 | 5% | ||
howo | 0 | 10,174,153,689 | 2.5% | ||
tsoldovieri | 0 | 321,433,486 | 2.5% | ||
nitego | 0 | 83,513,305 | 0.32% | ||
neumannsalva | 0 | 119,656,587 | 0.54% | ||
wargof | 0 | 237,368,220 | 10% | ||
abigail-dantes | 0 | 84,876,604,506 | 5% | ||
zonguin | 0 | 204,013,366 | 1.25% | ||
alexzicky | 0 | 991,622,714 | 1.25% | ||
mountain.phil28 | 0 | 3,577,967,737 | 25% | ||
tuoficinavirtual | 0 | 97,323,426 | 25% | ||
iamphysical | 0 | 13,070,682,450 | 90% | ||
nuthman | 0 | 2,443,189,729 | 0.48% | ||
zest | 0 | 890,992,453 | 2.5% | ||
felixrodriguez | 0 | 179,805,175 | 2.5% | ||
azulear | 0 | 1,943,465,742 | 100% | ||
psicoluigi | 0 | 287,345,736 | 50% | ||
massivevibration | 0 | 3,838,522,930 | 5% | ||
fbslo | 0 | 421,022,791 | 0.5% | ||
nicola71 | 0 | 131,559,845 | 0.87% | ||
erikkun28 | 0 | 0 | 1% | ||
filipino | 0 | 912,387,151 | 10% | ||
birddroppings | 0 | 2,451,741,988 | 10% | ||
mayowadavid | 0 | 175,141,592 | 2.5% | ||
emdesan | 0 | 135,158,735 | 10% | ||
peaceandwar | 0 | 127,014,247 | 0.54% | ||
enzor | 0 | 106,876,435 | 5% | ||
jesusj1 | 0 | 80,420,132 | 100% | ||
carloserp-2000 | 0 | 37,980,013,894 | 100% | ||
gra | 0 | 1,833,082,021 | 5% | ||
eonwarped | 0 | 456,753,006,117 | 100% | ||
aalok | 0 | 107,044,616 | 26% | ||
drmake | 0 | 542,272,885 | 0.54% | ||
guga34 | 0 | 84,876,935 | 3.75% | ||
amestyj | 0 | 2,950,956,619 | 50% | ||
mhm-philippines | 0 | 616,700,078 | 0.54% | ||
skycae | 0 | 96,501,852 | 1.08% | ||
woolnami | 0 | 638,503,329 | 0.32% | ||
kenadis | 0 | 1,159,357,754 | 5% | ||
maticpecovnik | 0 | 240,458,792 | 2% | ||
robotics101 | 0 | 438,577,623 | 5% | ||
ivymalifred | 0 | 1,454,728,852 | 50% | ||
ennyta | 0 | 1,894,208,307 | 50% | ||
rharphelle | 0 | 1,037,879,194 | 25% | ||
stahlberg | 0 | 173,901,233 | 0.54% | ||
vjap55 | 0 | 368,509,545 | 100% | ||
mangoish | 0 | 86,778,935 | 10% | ||
eliaschess333 | 0 | 4,911,041,238 | 50% | ||
ydavgonzalez | 0 | 1,380,434,793 | 5% | ||
langford | 0 | 209,880,503 | 5% | ||
mattiarinaldoni | 0 | 0 | 1% | ||
mathowl | 0 | 19,533,666,019 | 50% | ||
silkroadgo | 0 | 1,349,433,441 | 0.32% | ||
terrylovejoy | 0 | 796,783,715 | 2% | ||
traviseric | 0 | 220,761,467 | 50% | ||
yrmaleza | 0 | 873,510,217 | 50% | ||
mondodidave73 | 0 | 174,706,881 | 0.75% | ||
kingabesh | 0 | 112,915,119 | 2.5% | ||
miguelangel2801 | 0 | 788,854,424 | 50% | ||
didic | 0 | 551,874,154 | 0.54% | ||
fcdvpds | 0 | 1,637,794,517 | 2% | ||
therosepatch | 0 | 196,516,727 | 50% | ||
emiliomoron | 0 | 2,032,024,217 | 50% | ||
dexterdev | 0 | 519,906,664 | 2.5% | ||
nwjordan | 0 | 102,382,001 | 1.08% | ||
oghie | 0 | 587,105,138 | 50% | ||
geopolis | 0 | 283,934,645 | 5% | ||
robertbira | 0 | 482,137,392 | 1.25% | ||
alexdory | 0 | 1,927,204,607 | 2% | ||
aotearoa | 0 | 764,608,969 | 9% | ||
flugschwein | 0 | 2,128,704,017 | 4.75% | ||
benleemusic | 0 | 132,627,832 | 0.1% | ||
ulisesfl17 | 0 | 1,855,034,599 | 100% | ||
arac | 0 | 1,014,092,865 | 100% | ||
francostem | 0 | 641,588,166 | 5% | ||
ivan-g | 0 | 92,221,521 | 0.54% | ||
endopediatria | 0 | 694,849,803 | 20% | ||
croctopus | 0 | 1,412,520,050 | 100% | ||
sissyjill | 0 | 72,314,343 | 7% | ||
emmanuel293 | 0 | 100,214,836 | 25% | ||
morbyjohn | 0 | 138,700,365 | 7% | ||
positiveninja | 0 | 123,008,973 | 0.54% | ||
tomastonyperez | 0 | 6,871,236,977 | 50% | ||
elvigia | 0 | 6,156,974,844 | 50% | ||
qberry | 0 | 470,770,674 | 0.54% | ||
acknowledgement | 0 | 1,119,295,683 | 10% | ||
lesmouths-travel | 0 | 269,263,310 | 5% | ||
ezravandi | 0 | 397,944,176 | 1% | ||
effofex | 0 | 481,657,557 | 2.5% | ||
luiscd8a | 0 | 1,981,038,147 | 80% | ||
eniolw | 0 | 220,811,109 | 5% | ||
de-stem | 0 | 2,767,081,589 | 4.95% | ||
geadriana | 0 | 950,955,973 | 50% | ||
elpdl | 0 | 414,349,933 | 100% | ||
derbesserwisser | 0 | 20,468,946,536 | 100% | ||
serylt | 0 | 1,526,808,754 | 4.9% | ||
josedelacruz | 0 | 3,249,750,308 | 50% | ||
viannis | 0 | 1,536,636,053 | 50% | ||
flores39 | 0 | 414,807,607 | 100% | ||
majapesi | 0 | 248,960,104 | 50% | ||
sbi3 | 0 | 27,734,583,488 | 4.88% | ||
irelandscape | 0 | 16,876,614,634 | 100% | ||
deholt | 0 | 137,373,129 | 5% | ||
timothyallen | 0 | 826,173,371 | 0.54% | ||
temitayo-pelumi | 0 | 335,458,571 | 5% | ||
yusvelasquez | 0 | 418,787,954 | 50% | ||
alexworld | 0 | 58,618,049 | 25% | ||
frost1903 | 0 | 44,807,132 | 50% | ||
acont | 0 | 249,282,913 | 50% | ||
anaestrada12 | 0 | 10,710,382,039 | 100% | ||
steemzeiger | 0 | 228,899,754 | 4.95% | ||
council | 0 | 948,585,837 | 10% | ||
blewitt | 0 | 419,315,305 | 0.1% | ||
kafupraise | 0 | 81,907,365 | 34% | ||
biomimi | 0 | 189,707,760 | 40% | ||
drsensor | 0 | 651,759,290 | 4% | ||
abcor | 0 | 738,767,144 | 0.1% | ||
reyvaj | 0 | 788,041,053 | 2.5% | ||
jesusfl17 | 0 | 415,356,690 | 100% | ||
ilovecryptopl | 0 | 91,122,817 | 0.86% | ||
emsonic | 0 | 254,363,016 | 0.54% | ||
yomismosoy | 0 | 192,100,216 | 50% | ||
ubaldonet | 0 | 2,097,029,629 | 80% | ||
spbeckman | 0 | 2,200,207,200 | 100% | ||
yestermorrow | 0 | 270,174,457 | 1.25% | ||
call-me-howie | 0 | 155,995,985 | 0.54% | ||
mary11 | 0 | 293,997,605 | 75% | ||
rgkmb-unofficial | 0 | 2,093,140,001 | 35% | ||
rgkmb | 0 | 131,612,126 | 35% | ||
wstanley226 | 0 | 247,927,544 | 50% | ||
osariemen | 0 | 634,705,055 | 90% | ||
markgritter | 0 | 17,019,250,876 | 100% | ||
lupafilotaxia | 0 | 9,255,935,387 | 100% | ||
fran.frey | 0 | 1,815,314,561 | 50% | ||
alaiza | 0 | 485,844,755 | 100% | ||
jrevilla | 0 | 168,314,952 | 50% | ||
moniroy | 0 | 644,388,795 | 25% | ||
cmp2020-lite | 0 | 109,494,373 | 35% | ||
remlaps-lite | 0 | 122,485,754 | 35% | ||
skorup87 | 0 | 16,697,780 | 11% | ||
swapsteem | 0 | 79,895,109 | 2.5% | ||
stem-espanol | 0 | 38,427,203,292 | 100% | ||
praditya | 0 | 1,328,495,773 | 24% | ||
lapp | 0 | 485,844,767 | 100% | ||
steemtpistia | 0 | 485,306,871 | 100% | ||
crassipes | 0 | 485,560,767 | 100% | ||
javier.dejuan | 0 | 1,110,236,036 | 5% | ||
agrovision | 0 | 485,844,408 | 100% | ||
xeliram | 0 | 249,139,561 | 50% | ||
giulyfarci52 | 0 | 323,221,903 | 50% | ||
stem.witness | 0 | 1,736,236,492 | 5% | ||
monkeycatwithowl | 0 | 553,953,218 | 100% | ||
double-negative | 0 | 472,606,527 | 20% | ||
wilmer14molina | 0 | 1,693,428,033 | 100% | ||
kingnosa | 0 | 57,482,706 | 50% | ||
luna777 | 0 | 1,147,982,240 | 3.08% | ||
amin-ove | 0 | 80,778,447 | 50% | ||
hairgistix | 0 | 415,107,291 | 0.54% | ||
huilco | 0 | 333,373,774 | 100% | ||
steemmyphoto | 0 | 2,042,182,017 | 100% | ||
combatsports | 0 | 267,536,535 | 1.08% |
I mean, seriously, Haskell, WTF? Who need a maximum that is right-associative and lazy? ``` maximum :: forall a . Ord a => t a -> a maximum = fromMaybe (errorWithoutStackTrace "maximum: empty structure") . getMax . foldMap (Max #. (Just :: a -> Maybe a)) ``` `foldMap` uses `foldr` so `maximum` and `maximumBy` use different orders! Who wanted that!? >Note [maximumBy/minimumBy space usage] >When the type signatures of maximumBy and minimumBy were generalized to work over any Foldable instance (instead of just lists), they were defined using foldr1. This was problematic for space usage, as the semantics of maximumBy and minimumBy essentially require that they examine every element of the data structure. Using foldr1 to examine every element results in space usage proportional to the size of the data structure. For the common case of lists, this could be particularly bad (see Trac #10830). > For the common case of lists, switching the implementations of maximumBy and minimumBy to foldl1 solves the issue, as GHC's strictness analysis can then make these functions only use O(1) stack space. It is perhaps not the optimal way to fix this problem, as there are other conceivable data structures (besides lists) which might benefit from specialized implementations for maximumBy and minimumBy (see https://ghc.haskell.org/trac/ghc/ticket/10830#comment:26 for a further discussion). But using foldl1 is at least always better than using foldr1, so GHC has chosen to adopt that approach for now. Source: http://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.Foldable.html#maximum
author | markgritter |
---|---|
permlink | re-markgritter-advent-of-code-day-11-spoilers-inclusion-exclusion-and-haskell-s-odd-design-decisions-20190104t051808281z |
category | adventofcode |
json_metadata | {"tags":["adventofcode"],"links":["https://ghc.haskell.org/trac/ghc/ticket/10830#comment:26","http://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.Foldable.html#maximum"],"app":"steemit/0.1"} |
created | 2019-01-04 05:18:09 |
last_update | 2019-01-04 05:18:09 |
depth | 1 |
children | 0 |
last_payout | 2019-01-11 05:18:09 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 1,616 |
author_reputation | 7,057,249,855,552 |
root_title | "Advent of Code Day 11 [spoilers], Inclusion-Exclusion, and Haskell's odd design decisions" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 77,845,632 |
net_rshares | 0 |
<div class='text-justify'> <div class='pull-left'> <br /> <center> <img width='125' src='https://i.postimg.cc/9FwhnG3w/steemstem_curie.png'> </center> <br/> </div> <br /> <br /> This post has been voted on by the **SteemSTEM** curation team and voting trail in collaboration with **@curie**. <br /> If you appreciate the work we are doing then consider [voting](https://www.steemit.com/~witnesses) both projects for witness by selecting [**stem.witness**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=stem.witness) and [**curie**](https://steemconnect.com/sign/account_witness_vote?approve=1&witness=curie)! <br /> For additional information please join us on the [**SteemSTEM discord**]( https://discord.gg/BPARaqn) and to get to know the rest of the community! </div>
author | steemstem |
---|---|
permlink | re-markgritter-advent-of-code-day-11-spoilers-inclusion-exclusion-and-haskell-s-odd-design-decisions-20190104t092806012z |
category | adventofcode |
json_metadata | {"app":"bloguable-bot"} |
created | 2019-01-04 09:28:09 |
last_update | 2019-01-04 09:28:09 |
depth | 1 |
children | 0 |
last_payout | 2019-01-11 09:28:09 |
cashout_time | 1969-12-31 23:59:59 |
total_payout_value | 0.000 HBD |
curator_payout_value | 0.000 HBD |
pending_payout_value | 0.000 HBD |
promoted | 0.000 HBD |
body_length | 800 |
author_reputation | 262,017,435,115,313 |
root_title | "Advent of Code Day 11 [spoilers], Inclusion-Exclusion, and Haskell's odd design decisions" |
beneficiaries | [] |
max_accepted_payout | 1,000,000.000 HBD |
percent_hbd | 10,000 |
post_id | 77,853,527 |
net_rshares | 0 |