2026/04/06

Newest at the top

2026-04-06 11:34:22 +0000 <ski> but yes, the implementor of `||' (or whichever callback you're using)
2026-04-06 11:33:54 +0000 <ski> there is no `:' is the result of `foldr'
2026-04-06 11:33:44 +0000 <ski> not quite that
2026-04-06 11:33:41 +0000merijn(~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn
2026-04-06 11:33:26 +0000tromp(~textual@2001:1c00:340e:2700:795f:6a6f:7cb5:ecd6) (Quit: My iMac has gone to sleep. ZZZzzz…)
2026-04-06 11:29:38 +0000 <fp`> and the short-circuiting logic is down to... the implementor of (||)? Or ghc? Or is there even a runtime component?
2026-04-06 11:28:42 +0000 <fp`> foldr f acc x:xs = (f x acc) : (foldr f acc xs)
2026-04-06 11:28:41 +0000 <fp`> So foldr looks something like this (with an additional boundary condition)
2026-04-06 11:28:22 +0000 <lambdabot> True
2026-04-06 11:28:21 +0000 <ski> > foldr (||) False (map (> 10) [0 ..]) -- this hands over control to `||', which decides whether to continye with the next recursive `foldr' call or not
2026-04-06 11:26:50 +0000 <ski> `foldl' keeps control, until it reaches the end of the list
2026-04-06 11:26:25 +0000 <ski> `foldr' hands over control to the callback, and lets it decide if and when to continue with the `foldr' recursive call (being the second parameter passed to the callback)
2026-04-06 11:25:44 +0000 <lambdabot> f a (f b (f c z))
2026-04-06 11:25:42 +0000 <ski> > foldr f z [a,b,c] :: Expr
2026-04-06 11:25:40 +0000 <lambdabot> f (f (f z a) b) c
2026-04-06 11:25:39 +0000 <ski> > foldl f z [a,b,c] :: Expr
2026-04-06 11:25:25 +0000 <ski> both `foldl' and `foldr' start "from the left". what differs is the way it "associates" the callback (to the left, like `((z - a) - b) - c', for `foldl (-) z [a,b,c]', vs. to the right, like `a - (b - (c - z))', for `foldr (-) z [a,b,c]'). `foldl' keeps adding to, growing, the accumulator, while `foldr' wraps its recursive calls inside calls to the callback
2026-04-06 11:22:39 +0000merijn(~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 255 seconds)
2026-04-06 11:22:33 +0000xff0x(~xff0x@2405:6580:b080:900:388f:e7ec:f5bb:9bd0)
2026-04-06 11:22:03 +0000__monty__(~toonn@user/toonn) toonn
2026-04-06 11:21:38 +0000 <ski> (this is the "direct recursive" version)
2026-04-06 11:21:11 +0000 <ski> then basically the same thing would happen, as in the `foldr' version
2026-04-06 11:20:59 +0000 <ski> for the last defining equation
2026-04-06 11:20:54 +0000 <ski> putStr' (c:cs) = do putChar c; putStr' cs
2026-04-06 11:20:51 +0000 <ski> or, if you prefer
2026-04-06 11:20:44 +0000 <ski> putStr' (c:cs) = putChar c >> putStr' cs
2026-04-06 11:20:26 +0000 <ski> putStr' [ ] = return ()
2026-04-06 11:20:16 +0000 <ski> btw, do note that if you defined
2026-04-06 11:20:07 +0000__monty__(~toonn@user/toonn) (Ping timeout: 244 seconds)
2026-04-06 11:18:37 +0000 <ski> exactly
2026-04-06 11:18:31 +0000 <ski> do note that, as soon as the putChar 'a' has been executed, we don't need to keep memory around for it (although i showed it still in all the remaining lines above, for clarity), so we can discard that memory, and similarly for the other actions, so therefore we run in constant space
2026-04-06 11:18:08 +0000 <fp`> Mm so it's not actually iterating from the right
2026-04-06 11:17:41 +0000 <ski> { and now the return () which does nothing }
2026-04-06 11:17:24 +0000 <ski> = putChar 'a' >> putChar 'b' >> putChar 'c' >> return ()
2026-04-06 11:17:15 +0000 <ski> { and now the putChar 'c' happens }
2026-04-06 11:17:04 +0000 <ski> = putChar 'a' >> putChar 'b' >> putChar 'c' >> foldr (\c acc -> putChar c >> acc) (return ()) []
2026-04-06 11:16:53 +0000 <ski> { at this point, the putChar 'b' part is executed }
2026-04-06 11:16:34 +0000 <ski> = putChar 'a' >> putChar 'b' >> foldr (\c acc -> putChar c >> acc) (return ()) [c']
2026-04-06 11:16:20 +0000 <ski> { at this point, `main' / the interactor sees that the action is an `>>'-action, with first sub-action being putChar 'a' so it performs that part now, and then tries to perform the second one, which triggers the evaluation of it, so that `foldr' continunes one more step. i'll show putChar 'a' still as part of the result value (action), but remember that it has already happened now}
2026-04-06 11:15:53 +0000merijn(~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn
2026-04-06 11:14:54 +0000 <ski> = putChar 'a' >> foldr (\c acc -> putChar c >> acc) (return ()) ['b','c']
2026-04-06 11:14:43 +0000 <ski> foldr (\c acc -> putChar c >> acc) (return ()) ['a','b','c']
2026-04-06 11:14:22 +0000 <ski> ok, so here's what happens
2026-04-06 11:13:07 +0000 <fp`> or foldr (\c acc -> putChar c >> acc) (return ()) "abc"
2026-04-06 11:12:19 +0000 <fp`> (\c acc -> putChar c >> acc)
2026-04-06 11:10:41 +0000 <ski> (a direct recursion would also be fine)
2026-04-06 11:10:20 +0000 <ski> if you define the `foldr' version, i can then explain why it's better here
2026-04-06 11:09:53 +0000 <fp`> But why would foldr be better? Since I'm iterating through the list backward, I can't even start thinking about IO actions until I know what the first thing to print is
2026-04-06 11:09:22 +0000 <ski> and `>>=' is "bind"
2026-04-06 11:09:12 +0000 <gentauro> (Y)