2025/01/31

2025-01-31 00:04:43 +0100weary-traveler(~user@user/user363627) user363627
2025-01-31 00:06:53 +0100 <glguy> My favorite Data. misuse is Data.Kind
2025-01-31 00:07:03 +0100 <tomsmeding> (re mechanisms to resolve ambiguity: https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/package_qualified_imports.html#exte… )
2025-01-31 00:09:21 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 00:10:58 +0100 <dminuoso> Relatedly https://downloads.haskell.org/ghc/latest/docs/users_guide/packages.html#package-thinning-and-renam…
2025-01-31 00:11:36 +0100 <dminuoso> Unsure how controllable that is via cabal-install
2025-01-31 00:12:28 +0100 <geekosaur> "mixins" should handle both
2025-01-31 00:12:53 +0100eL_Bart0(eL_Bart0@dietunichtguten.org) (Ping timeout: 245 seconds)
2025-01-31 00:13:43 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds)
2025-01-31 00:14:40 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 00:14:57 +0100ljdarj(~Thunderbi@user/ljdarj) (Ping timeout: 248 seconds)
2025-01-31 00:18:50 +0100 <dminuoso> A while ago transformers has received these nice diagrams to visualize what the respective transformers do: https://hackage.haskell.org/package/transformers-0.6.1.2/docs/Control-Monad-Trans-Writer-CPS.html
2025-01-31 00:19:06 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 00:19:09 +0100 <dminuoso> We're just missing a diagram for Cont. Cant be that hard, right? :-)
2025-01-31 00:19:28 +0100 <geekosaur> i,i "Cont be that hard"
2025-01-31 00:19:37 +0100 <dminuoso> Heh.
2025-01-31 00:21:02 +0100 <EvanR> haskell is famous for laissez faire programming. Terrible I'm outta here
2025-01-31 00:21:02 +0100 <int-e> please pass all the details to `const "I don't want to hear it."`
2025-01-31 00:21:15 +0100 <EvanR> looking for a language for more bondage and discipline
2025-01-31 00:22:30 +0100 <geekosaur> surely there's an appropriate DT language
2025-01-31 00:23:03 +0100rstromlund(~user@user/rstromlund) (Ping timeout: 252 seconds)
2025-01-31 00:24:45 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 00:28:15 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) Smiles
2025-01-31 00:31:37 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 265 seconds)
2025-01-31 00:31:59 +0100haskellbridge(~hackager@syn-024-093-192-219.res.spectrum.com) (Remote host closed the connection)
2025-01-31 00:32:46 +0100haskellbridge(~hackager@syn-024-093-192-219.res.spectrum.com) hackager
2025-01-31 00:32:46 +0100ChanServ+v haskellbridge
2025-01-31 00:35:39 +0100 <monochrom> You know what, I have to understand Reader and Writer first before I understand those two diagrams.
2025-01-31 00:35:57 +0100xff0x(~xff0x@ai096095.d.east.v6connect.net) (Ping timeout: 252 seconds)
2025-01-31 00:36:07 +0100 <monochrom> And generally I have to understand bind first.
2025-01-31 00:37:39 +0100 <monochrom> But State is missing a diagram and that's a well-known diagram.
2025-01-31 00:38:06 +0100xff0x(~xff0x@2405:6580:b080:900:704:c9bd:a645:9b1d)
2025-01-31 00:38:22 +0100 <monochrom> Conjecture: Such a diagram exists iff the monad is of an algebraic effect. Cont is not an algebraic effect.
2025-01-31 00:42:48 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 00:42:51 +0100sawilagar(~sawilagar@user/sawilagar) (Ping timeout: 252 seconds)
2025-01-31 00:44:14 +0100joeyadams(~joeyadams@syn-184-054-105-097.res.spectrum.com)
2025-01-31 00:46:35 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 252 seconds)
2025-01-31 00:47:34 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 00:49:59 +0100monochrom(trebla@216.138.220.146)
2025-01-31 00:52:02 +0100 <euouae> <https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State> "A monad is sometimes described as providing a value in a context." -- this is very close to what I was thinking when I said monads are like state machines
2025-01-31 00:54:15 +0100 <dminuoso> euouae: Monads are an abstract interface.
2025-01-31 00:54:36 +0100 <dminuoso> Comparing them to anything concrete is, at best, just likening it to that specific instance, but that prevents you from seeing what monad is about.
2025-01-31 00:54:52 +0100 <int-e> now I want a burrito
2025-01-31 00:55:16 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 00:57:25 +0100 <dminuoso> euouae: My best recommendation is to just not worry about what Monad means at all. `IO` is about side effects. `[]` is about lists. `Maybe` is about failure. `Either A` is about exceptions. Each example is trivial to explain to any beginner
2025-01-31 00:58:09 +0100 <dminuoso> Monad is just observing that all of these things have some pattern and laws in common. There's not really any inherent meaning to it
2025-01-31 00:58:40 +0100 <dminuoso> And if people stop trying to attach meaning to that word `Monad`, they get on learning Haskell much faster.
2025-01-31 00:58:45 +0100 <monochrom> I do not mind specific instances that may limit one's imagination because it is part of the learning process.
2025-01-31 00:59:48 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 01:00:31 +0100rstromlund(~user@user/rstromlund) rstromlund
2025-01-31 01:00:41 +0100 <monochrom> Consider how "numbers" are taught beginning with natural numbers and, eventually, if you go to math grad school, ending with algebraic number fields. Not the other way round.
2025-01-31 01:01:00 +0100 <dminuoso> monochrom: Sure, but that particular wikibooks article is not about promoting any learning process.
2025-01-31 01:01:22 +0100 <dminuoso> If Monad tutorials started with just proclamining `Monads are just IO`, this would be a feasible strategy.
2025-01-31 01:01:44 +0100 <dminuoso> As you could gradually introduce more instances and different "flavours"
2025-01-31 01:02:54 +0100 <monochrom> That one I agree with you. It's the equivalent of a biology tutorial saying "natural selection is described as survival of fittest"
2025-01-31 01:04:03 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 01:05:18 +0100rstromlund(~user@user/rstromlund) (Ping timeout: 252 seconds)
2025-01-31 01:08:34 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 01:08:58 +0100 <euouae> dminuoso: I'm not trying to summarize all monads or anything of the short, just to adopt a mental mode
2025-01-31 01:10:04 +0100 <dminuoso> euouae: Fair enough.
2025-01-31 01:10:25 +0100 <euouae> obviously it's both tiresome to manually typecheck everything when reading code & provides no intuition. the megaparsec code I saw earlier with a bunch of >>= inside a do was clear in what it was doing: it was combining a bunch of parser combinators, starting from some initial string-to-be-parsed, and outputted either a parsed data structure or parser error
2025-01-31 01:10:34 +0100 <dminuoso> The mental model I have settled on over the years is that `Monads` model sequencing.
2025-01-31 01:10:39 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 01:10:43 +0100 <euouae> and it sort of occurred to me that a lot of uses of do/>>= are doing basically stuff like that
2025-01-31 01:11:39 +0100 <dminuoso> Though Im a flexible, and I have some alternate intuitions that I can switch to depending on the problem.
2025-01-31 01:12:02 +0100 <euouae> well sure, adopting just one is good enough for me. I'll adopt more if the need arises
2025-01-31 01:12:10 +0100down200(~down200@shell.lug.mtu.edu) (Ping timeout: 244 seconds)
2025-01-31 01:12:50 +0100 <dminuoso> euouae: [] seems to breaks a state machine viewpoint.
2025-01-31 01:13:12 +0100 <dminuoso> The monad instance of [] roughly models non-determinism (with a bit of squinting)
2025-01-31 01:13:19 +0100 <euouae> if you can elaborate?
2025-01-31 01:13:27 +0100monochrm(trebla@216.138.220.146)
2025-01-31 01:14:31 +0100 <dminuoso> (I say squinting because lists are not sets and have a bit more structure)
2025-01-31 01:15:11 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 01:15:24 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 260 seconds)
2025-01-31 01:15:24 +0100monochrmmonochrom
2025-01-31 01:15:52 +0100 <geekosaur> so, the list monad models a computation that gives you all possible solutions, whereas a Maybe version of the same computation gives you at most one solution (and can be thought of as "first solution, if any")
2025-01-31 01:17:35 +0100down200(~down200@shell.lug.mtu.edu) down200
2025-01-31 01:18:11 +0100 <dminuoso> euouae: Say if we imagine a chess computer, we could think of [move1, move2, move3, move4] as not a collection of possibilities, but rather some non-deterministic choice of *one* move.
2025-01-31 01:18:24 +0100ec(~ec@gateway/tor-sasl/ec) ec
2025-01-31 01:18:34 +0100 <dminuoso> And >>= lets you take a further non-determistic choice
2025-01-31 01:19:09 +0100 <euouae> Here's how lists are state machines: No input variable, only state; its output is the state. They compose funkily, but still.
2025-01-31 01:19:23 +0100 <geekosaur> as dminuoso said, it's acting as a "poor man's set" (for technical reasons we can't actually make a Set a Monad); all the answers are equally ranked, their position in the list isn't relevant
2025-01-31 01:19:52 +0100 <dminuoso> euouae: But its that *funkily* behavior that is the core essence of that instance.
2025-01-31 01:20:02 +0100 <euouae> It is no less a state machine however
2025-01-31 01:20:08 +0100 <euouae> a composable state machine, as I said above
2025-01-31 01:20:41 +0100 <euouae> anyway, it's been said that everything can be considered a state machine, it's just a mental mode I have... I'm just glad I put it to some test and it didn't immediately collapse
2025-01-31 01:20:44 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) bitdex
2025-01-31 01:21:37 +0100 <dminuoso> I mean if you insist on that state machine model, perhaps you could think of it as a non-deterministic state machine (along the lines of an NFA)
2025-01-31 01:22:08 +0100 <dminuoso> Im not sure about the exact mental gymnastics required to see the state machine, but thats probably because Im flexed very differently
2025-01-31 01:23:01 +0100geekosaurwonders if it's the same viewpoint used with the comonad
2025-01-31 01:23:07 +0100 <dminuoso> euouae: So here's why your state machine logic does not quite work out:
2025-01-31 01:23:18 +0100 <euouae> As long as I can squeeze real-world results from my intuition I'm not too bothered by its rough edges
2025-01-31 01:23:24 +0100 <dminuoso> euouae: `do x <- [1,2,3]; ...` -> how do you obtain the state?
2025-01-31 01:24:01 +0100 <dminuoso> The non-determinism approach has the benefit of accurately modelling non-deterministic algorithms.
2025-01-31 01:24:57 +0100 <dminuoso> In the above example, `x` represents some non-deterministic choice of [1,2,3]
2025-01-31 01:25:01 +0100 <euouae> In `do x <- [1,2,3];` you're getting a slice of that funky composability
2025-01-31 01:25:24 +0100 <dminuoso> euouae: But Im asking about where that state machine is. What's the state here?
2025-01-31 01:25:38 +0100 <euouae> now x <- [1,1,1] does not have enough information for you to distinguish one 1 from another 1, even though they're positionally different
2025-01-31 01:26:01 +0100 <euouae> I think I imagine state different from State or whatever
2025-01-31 01:26:02 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 01:26:11 +0100 <euouae> The state is [1,2,3]
2025-01-31 01:26:41 +0100 <dminuoso> euouae: Thats only true in the sense that the program has to store [1,2,3], but that could be said about *any* computation of anything.
2025-01-31 01:27:03 +0100 <dminuoso> euouae: If we want to derive meaning of Monad, we must constrain to its interface
2025-01-31 01:27:05 +0100 <dminuoso> % :t pure
2025-01-31 01:27:06 +0100 <yahb2> pure :: Applicative f => a -> f a
2025-01-31 01:27:11 +0100 <dminuoso> % :t (>>=)
2025-01-31 01:27:11 +0100 <yahb2> (>>=) :: Monad m => m a -> (a -> m b) -> m b
2025-01-31 01:27:36 +0100 <dminuoso> If you cannot put your "state" into relationship with that interface, your intuition has nothing to do with Monad, but with something else.
2025-01-31 01:27:56 +0100 <dminuoso> These two functions, *together with some laws* are what Monad is. Nothing more, nothing less.
2025-01-31 01:28:08 +0100 <euouae> Like I said, it's matching some usual applications of Monad like the parser combinators
2025-01-31 01:28:25 +0100 <euouae> You want to content that it's not matching List. I agree, but at the same time, I am not too afraid to stretch my imagination and pretend it does
2025-01-31 01:28:40 +0100 <euouae> As long as I can get somewhere with megaparsec :P
2025-01-31 01:28:49 +0100 <euouae> anyway sorry for wasting your time... just thoughts
2025-01-31 01:28:50 +0100 <dminuoso> euouae: Your intuitoin is absolutely great for megaparsec.
2025-01-31 01:29:10 +0100 <dminuoso> But its not a good general intuition, it just does not work for list.
2025-01-31 01:30:37 +0100 <dminuoso> euouae: In fact, megaparsec under the hood could be thought of StateT and ExceptT wired together - thats state looks so fitting, because it *does* use a state monad internally.
2025-01-31 01:30:59 +0100 <euouae> What is the role of T in StateT? I haven't quite grasped that
2025-01-31 01:31:02 +0100 <dminuoso> (Internally it uses a different representation for performance reasons, miond you)
2025-01-31 01:31:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 272 seconds)
2025-01-31 01:31:12 +0100 <euouae> I haven't seen any examples either. I know a monad goes there, but State has it to be Identity
2025-01-31 01:31:25 +0100 <hololeap> it stands for "transformer"
2025-01-31 01:33:18 +0100 <dminuoso> euouae: And perhaps, for IO the state notion is not too shabby either as a first try by the way, if we think of the "real world" being the state. This is an intuition I can easily prove wrong, but I think I would rob you of some valuable learning process as monochrom as pointed out earlier.
2025-01-31 01:33:43 +0100 <dminuoso> Given that you could just `launchMissiles` and change the state of the real world with IO.
2025-01-31 01:34:33 +0100 <hololeap> I can't remember how to do 'unmtl' in #haskell
2025-01-31 01:34:34 +0100 <euouae> I'm not sure what you mean by proving it wrong
2025-01-31 01:34:55 +0100 <euouae> Is IO not a state
2025-01-31 01:35:03 +0100 <dminuoso> euouae: There's a bunch of things you can do in IO that... isnt quite about changing the real world.
2025-01-31 01:35:22 +0100 <dminuoso> Or you would need to do some more gymnastics.
2025-01-31 01:35:25 +0100 <hololeap> IO being (State RealWorld a) is more of a mental model
2025-01-31 01:35:44 +0100 <dminuoso> euouae: I dont want discredit this particular intuition, because I think it *is* a good starting point
2025-01-31 01:36:12 +0100 <dminuoso> Just like we teach newtonian physics in school, despite general relativity being more accurate.
2025-01-31 01:37:03 +0100 <dminuoso> euouae: Anyhow. Do try to build the state intuition around `>>=` and `pure` - and then test it in the future.
2025-01-31 01:37:19 +0100 <euouae> yup. thank you
2025-01-31 01:37:24 +0100 <euouae> but what is transformer?
2025-01-31 01:37:49 +0100 <dminuoso> euouae: If we think of Monads not as "state" but as some generalized idea of effects, then transformers lets us combine different effects.
2025-01-31 01:37:53 +0100 <euouae> With a State I know I have a 'state processor' and an 'output value' but what is the transformer for?
2025-01-31 01:37:55 +0100 <dminuoso> THat may or may not make any sense to you.
2025-01-31 01:38:20 +0100 <dminuoso> euouae: StateT allows you to drag some state around, while ExceptT allows you to throw exceptions.
2025-01-31 01:38:33 +0100 <geekosaur> so, StateT doesn't just model state; it adds state to something. It transforms something else by adding state to it
2025-01-31 01:38:35 +0100 <dminuoso> Them being transformers means you can layer them ontop of each other, giving you a Monad that has both state *and* exceptions.
2025-01-31 01:39:00 +0100 <dminuoso> And if you add ListT (which adds non-determinism), you could have non-determinism, state and exceptions
2025-01-31 01:39:17 +0100 <dminuoso> ANd you can layer it over IO to have state, non-determinism, exceptions and real world nuclear missile effects.
2025-01-31 01:40:04 +0100 <dminuoso> euouae: Lets pick a more concrete examplee:
2025-01-31 01:40:29 +0100 <dminuoso> euouae: Your megaparsec parser can run either in pure mode, or it can run together with IO.
2025-01-31 01:40:55 +0100 <dminuoso> If you use it together with IO, you can interleave your parser with IO - say print statements or database calls
2025-01-31 01:41:14 +0100 <dminuoso> The reason you can do this, is because all this parsing effect is in a transformer ParsecT which you can layer over any other monad.
2025-01-31 01:41:25 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 01:41:46 +0100 <dminuoso> If you dont want IO, you can just layer it over `Identity`, which is sort of the "does nothing monad", giving you just the parsing effects.
2025-01-31 01:42:06 +0100 <dminuoso> https://hackage.haskell.org/package/megaparsec-9.7.0/docs/Text-Megaparsec.html#t:Parsec
2025-01-31 01:42:13 +0100 <dminuoso> type Parsec e s = ParsecT e s Identity
2025-01-31 01:43:15 +0100 <dminuoso> You can also use `ParsecT e s IO`, then you can suddenly do `liftIO (putStrLn "Hello world")` in the middle of your parser. Note, that because megaparsec will do backtracking this will have some interesting/strange behavior... which is non-determinism in fact.
2025-01-31 01:43:29 +0100 <dminuoso> (Assuming you use `try` of course)
2025-01-31 01:44:15 +0100 <euouae> right
2025-01-31 01:44:32 +0100 <euouae> I'm going to assume that it'll leak out the details of try
2025-01-31 01:45:16 +0100monochrm(trebla@216.138.220.146)
2025-01-31 01:45:40 +0100 <euouae> I think my composable state machine intuition is running into trouble with StateT. Transformers seem like a different beast, I'll have to think about it more.
2025-01-31 01:45:55 +0100 <euouae> But your example is very helpful, to keep in mind pure computation / IO stuff inside parsing
2025-01-31 01:46:00 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 01:46:29 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 260 seconds)
2025-01-31 01:46:30 +0100monochrmmonochrom
2025-01-31 01:48:52 +0100mange(~user@user/mange) mange
2025-01-31 01:48:53 +0100 <dminuoso> euouae: One last thing: That "funky composition" you talked about, that's where the monad lies. :-)
2025-01-31 01:49:18 +0100 <dminuoso> Just keep that thought mind for the future
2025-01-31 01:49:55 +0100 <dminuoso> % :t join
2025-01-31 01:49:55 +0100 <yahb2> <interactive>:1:1: error: [GHC-88464] Variable not in scope: join
2025-01-31 01:50:01 +0100 <dminuoso> % import Control.Monad
2025-01-31 01:50:01 +0100 <yahb2> <no output>
2025-01-31 01:50:03 +0100 <dminuoso> % :t join
2025-01-31 01:50:03 +0100 <yahb2> join :: Monad m => m (m a) -> m a
2025-01-31 01:50:58 +0100 <dminuoso> euouae: This is an alternate description of (>>=), and it perhaps visualizes nicely that there's a sort of composition idea going on.
2025-01-31 01:51:10 +0100 <dminuoso> Anyway. This was just meant as a teaser.
2025-01-31 01:51:47 +0100rstromlund(~user@user/rstromlund) rstromlund
2025-01-31 01:52:28 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 01:52:40 +0100 <int-e> @djinn ((((a -> r) -> r) -> r) -> r) -> (a -> r) -> r
2025-01-31 01:52:41 +0100 <lambdabot> f a b = a (\ c -> c b)
2025-01-31 01:53:06 +0100acidjnk_new3(~acidjnk@p200300d6e7283f4679216c0ad7f4b91d.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
2025-01-31 01:54:15 +0100xff0x(~xff0x@2405:6580:b080:900:704:c9bd:a645:9b1d) (Ping timeout: 276 seconds)
2025-01-31 01:56:36 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 01:56:40 +0100rstromlund(~user@user/rstromlund) (Ping timeout: 265 seconds)
2025-01-31 01:56:47 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 02:01:09 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 246 seconds)
2025-01-31 02:02:24 +0100joeyadams(~joeyadams@syn-184-054-105-097.res.spectrum.com) (Quit: Leaving)
2025-01-31 02:03:12 +0100 <hololeap> @unmtl StateT Int IO String
2025-01-31 02:03:12 +0100 <lambdabot> Int -> IO (String, Int)
2025-01-31 02:03:18 +0100 <hololeap> nice, there we go
2025-01-31 02:12:12 +0100sprotte24(~sprotte24@p200300d16f0f520069bfd2b9cee1df34.dip0.t-ipconnect.de) (Quit: Leaving)
2025-01-31 02:12:20 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 02:16:32 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds)
2025-01-31 02:18:49 +0100rstromlund(~user@user/rstromlund) rstromlund
2025-01-31 02:20:44 +0100otto_s(~user@p5b0441ee.dip0.t-ipconnect.de) (Ping timeout: 260 seconds)
2025-01-31 02:22:30 +0100otto_s(~user@p5de2fd05.dip0.t-ipconnect.de)
2025-01-31 02:24:26 +0100monochrm(trebla@216.138.220.146)
2025-01-31 02:25:58 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 252 seconds)
2025-01-31 02:25:58 +0100monochrmmonochrom
2025-01-31 02:26:00 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Ping timeout: 264 seconds)
2025-01-31 02:27:42 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 02:32:24 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 02:34:34 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 02:37:55 +0100xff0x(~xff0x@fsb6a9491c.tkyc517.ap.nuro.jp)
2025-01-31 02:38:26 +0100Sgeo(~Sgeo@user/sgeo) (Read error: Connection reset by peer)
2025-01-31 02:38:57 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 246 seconds)
2025-01-31 02:38:58 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 244 seconds)
2025-01-31 02:39:26 +0100monochrom(trebla@216.138.220.146)
2025-01-31 02:41:13 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 02:44:56 +0100Sgeo(~Sgeo@user/sgeo) Sgeo
2025-01-31 02:45:59 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 265 seconds)
2025-01-31 02:49:53 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 02:51:25 +0100Square2(~Square4@user/square) Square
2025-01-31 02:54:28 +0100Square(~Square@user/square) (Ping timeout: 244 seconds)
2025-01-31 02:54:44 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 03:04:16 +0100weary-traveler(~user@user/user363627) (Remote host closed the connection)
2025-01-31 03:05:17 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 03:06:03 +0100mikess(~mikess@user/mikess) mikess
2025-01-31 03:09:17 +0100 <euouae> why is `State s a` but `state :: a -> (a, s)`? the order is reversed
2025-01-31 03:09:41 +0100 <euouae> sorry, I mean, state :: Monad m => (s -> (a, s)) -> StateT s m a
2025-01-31 03:12:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 03:16:04 +0100Tuplanolla(~Tuplanoll@91-159-69-59.elisa-laajakaista.fi) (Quit: Leaving.)
2025-01-31 03:23:20 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 03:25:04 +0100mikess(~mikess@user/mikess) (Ping timeout: 272 seconds)
2025-01-31 03:26:30 +0100Sgeo(~Sgeo@user/sgeo) (Read error: Connection reset by peer)
2025-01-31 03:29:10 +0100Sgeo(~Sgeo@user/sgeo) Sgeo
2025-01-31 03:29:36 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 03:31:58 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds)
2025-01-31 03:33:37 +0100Tikosh(~quassel@user/Tikosh) Tikosh
2025-01-31 03:34:24 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 03:35:43 +0100 <Tikosh> https://www.youtube.com/watch?v=Qu0wtz6Z5RY
2025-01-31 03:35:50 +0100 <Tikosh> oh sorry
2025-01-31 03:35:56 +0100 <Tikosh> i thought this was gentoo-chat
2025-01-31 03:36:00 +0100 <Tikosh> excuse me
2025-01-31 03:43:07 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 03:46:01 +0100monochrm(trebla@216.138.220.146)
2025-01-31 03:47:28 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 245 seconds)
2025-01-31 03:47:29 +0100monochrmmonochrom
2025-01-31 03:47:39 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 03:55:24 +0100weary-traveler(~user@user/user363627) user363627
2025-01-31 03:55:54 +0100sarna(~sarna@d224-221.icpnet.pl) (Ping timeout: 252 seconds)
2025-01-31 03:56:32 +0100rstromlund(~user@user/rstromlund) (Ping timeout: 252 seconds)
2025-01-31 03:58:29 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 04:02:45 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 248 seconds)
2025-01-31 04:04:12 +0100peterbecich(~Thunderbi@syn-047-229-123-186.res.spectrum.com) peterbecich
2025-01-31 04:04:44 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 04:07:19 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 04:12:09 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 04:12:55 +0100monochrm(trebla@216.138.220.146)
2025-01-31 04:13:24 +0100sarna(~sarna@d224-221.icpnet.pl) sarna
2025-01-31 04:14:03 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 252 seconds)
2025-01-31 04:14:04 +0100monochrmmonochrom
2025-01-31 04:17:11 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2025-01-31 04:18:21 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 04:22:33 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 04:22:41 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 04:25:04 +0100 <monochrom> hololeap: @unmtl StateT s (ContT r IO) a
2025-01-31 04:25:10 +0100 <monochrom> @unmtl StateT s (ContT r IO) a
2025-01-31 04:25:10 +0100 <lambdabot> s -> (a -> s -> IO r) -> IO r
2025-01-31 04:27:20 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 04:30:44 +0100monochrm(trebla@216.138.220.146)
2025-01-31 04:30:49 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 260 seconds)
2025-01-31 04:30:55 +0100monochrmmonochrom
2025-01-31 04:31:25 +0100 <monochrom> The connection between the [] monad and state machines is at best this little: from the [] monad get the corresponding Kleisli arrow, then that would be nondeterministic state transition functions, i.e., of the form S -> [S].
2025-01-31 04:32:34 +0100 <monochrom> But that is as quaint as saying: endofunctions S -> S "Is" deterministic state machines just because deterministic state transition functions are of the form S->S. Clearly, in both cases, you are still missing out on: Who is the initial state? Who are accept states?
2025-01-31 04:33:07 +0100 <monochrom> I cannot accept (pun!) the confused conflation between state transition functions and state machines.
2025-01-31 04:34:50 +0100 <monochrom> It's like saying that Int is (Int, Char) because Int is one field of (Int, Char).
2025-01-31 04:38:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 04:43:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 04:44:33 +0100td_(~td@i53870904.versanet.de) (Ping timeout: 252 seconds)
2025-01-31 04:46:23 +0100td_(~td@i5387092E.versanet.de) td_
2025-01-31 04:55:35 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 05:00:42 +0100machinedgod(~machinedg@d108-173-18-100.abhsia.telus.net) (Ping timeout: 272 seconds)
2025-01-31 05:01:44 +0100monochrm(trebla@216.138.220.146)
2025-01-31 05:01:50 +0100 <euouae> so if you talk about state transition functions do you accept that monads are just composable state transition functions?
2025-01-31 05:01:57 +0100 <euouae> and i.e. it applies to lists?
2025-01-31 05:02:11 +0100 <euouae> as far as I can tell when you speak of the kleisli arrow you're just talking about lists of lists etc
2025-01-31 05:03:38 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 252 seconds)
2025-01-31 05:03:38 +0100monochrmmonochrom
2025-01-31 05:05:10 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 265 seconds)
2025-01-31 05:05:17 +0100 <monochrom> S->[S] is not list of list.
2025-01-31 05:06:45 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 05:06:47 +0100 <euouae> sure, [S]->[[S]] etc
2025-01-31 05:06:58 +0100 <monochrom> And I don't see in what sense A -> Cont R A is state transition function.
2025-01-31 05:07:28 +0100 <euouae> I'm not sure I follow but it's ok don't worry. I'm just doing some easy challenges on leetcode to get a grip on Haskell
2025-01-31 05:07:40 +0100peterbecich(~Thunderbi@syn-047-229-123-186.res.spectrum.com) (Ping timeout: 252 seconds)
2025-01-31 05:11:04 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 05:15:57 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 05:20:34 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 05:25:40 +0100aforemny(~aforemny@i577B135A.versanet.de) aforemny
2025-01-31 05:26:14 +0100aforemny_(~aforemny@2001:9e8:6ce3:9600:2c48:7088:cbda:dd4) (Ping timeout: 260 seconds)
2025-01-31 05:30:17 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
2025-01-31 05:30:33 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de)
2025-01-31 05:31:21 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 05:34:55 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer)
2025-01-31 05:35:50 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de)
2025-01-31 05:35:53 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 05:43:01 +0100kritzefitz(~kritzefit@debian/kritzefitz) (Ping timeout: 248 seconds)
2025-01-31 05:43:08 +0100pavonia(~user@user/siracusa) (Quit: Bye!)
2025-01-31 05:46:43 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 05:48:55 +0100monochrm(trebla@216.138.220.146)
2025-01-31 05:50:36 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 265 seconds)
2025-01-31 05:50:37 +0100monochrmmonochrom
2025-01-31 05:51:13 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds)
2025-01-31 05:51:15 +0100michalz(~michalz@185.246.207.221)
2025-01-31 05:53:07 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) bitdex
2025-01-31 05:55:09 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 05:55:16 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 05:59:13 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 244 seconds)
2025-01-31 06:00:14 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 272 seconds)
2025-01-31 06:02:27 +0100Digitteknohippie(~user@user/digit) Digit
2025-01-31 06:04:05 +0100tabaqui1(~root@87.200.129.102) (Ping timeout: 244 seconds)
2025-01-31 06:06:14 +0100Digit(~user@user/digit) (Killed (copper.libera.chat (Nickname regained by services)))
2025-01-31 06:06:14 +0100DigitteknohippieDigit
2025-01-31 06:06:56 +0100Guest8048(~user@250.88.90.146.dyn.plus.net)
2025-01-31 06:07:41 +0100Guest8048(~user@250.88.90.146.dyn.plus.net) (Remote host closed the connection)
2025-01-31 06:08:19 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 06:13:42 +0100califax(~califax@user/califx) (Remote host closed the connection)
2025-01-31 06:13:59 +0100califax(~califax@user/califx) califx
2025-01-31 06:14:54 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 246 seconds)
2025-01-31 06:23:33 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 248 seconds)
2025-01-31 06:26:22 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 06:27:20 +0100monochrom(trebla@216.138.220.146)
2025-01-31 06:31:13 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 265 seconds)
2025-01-31 06:33:16 +0100vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2025-01-31 06:37:22 +0100takuan(~takuan@d8D86B601.access.telenet.be)
2025-01-31 06:41:45 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 06:43:45 +0100Tikosh(~quassel@user/Tikosh) (Remote host closed the connection)
2025-01-31 06:43:49 +0100monochrm(trebla@216.138.220.146)
2025-01-31 06:44:13 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 06:44:44 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 265 seconds)
2025-01-31 06:44:45 +0100monochrmmonochrom
2025-01-31 06:44:48 +0100ensyde(~ensyde@2601:5c6:c200:6dc0::64a2)
2025-01-31 06:46:44 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 06:48:29 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 06:54:59 +0100tnt2(~Thunderbi@user/tnt1) tnt1
2025-01-31 06:55:23 +0100rvalue(~rvalue@user/rvalue) (Read error: Connection reset by peer)
2025-01-31 06:55:29 +0100tnt1(~Thunderbi@user/tnt1) (Ping timeout: 260 seconds)
2025-01-31 06:55:29 +0100tnt2tnt1
2025-01-31 06:55:55 +0100rvalue(~rvalue@user/rvalue) rvalue
2025-01-31 06:57:07 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 07:01:42 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 07:03:22 +0100monochrm(trebla@216.138.220.146)
2025-01-31 07:03:32 +0100vanishingideal(~vanishing@user/vanishingideal) (Ping timeout: 252 seconds)
2025-01-31 07:04:50 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 244 seconds)
2025-01-31 07:04:50 +0100monochrmmonochrom
2025-01-31 07:09:19 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 07:13:43 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds)
2025-01-31 07:15:48 +0100ft(~ft@p3e9bcd97.dip0.t-ipconnect.de) (Quit: leaving)
2025-01-31 07:24:06 +0100weary-traveler(~user@user/user363627) (Remote host closed the connection)
2025-01-31 07:24:42 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 07:24:48 +0100Square(~Square@user/square) Square
2025-01-31 07:26:18 +0100alp(~alp@2001:861:8ca0:4940:465c:30a2:2211:b30f) (Remote host closed the connection)
2025-01-31 07:26:35 +0100alp(~alp@2001:861:8ca0:4940:465c:30a2:2211:b30f)
2025-01-31 07:28:54 +0100Square2(~Square4@user/square) (Ping timeout: 260 seconds)
2025-01-31 07:29:09 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 248 seconds)
2025-01-31 07:32:37 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 07:33:09 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de) (Ping timeout: 252 seconds)
2025-01-31 07:33:23 +0100euleritian(~euleritia@dynamic-176-006-140-003.176.6.pool.telefonica.de)
2025-01-31 07:36:53 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 07:36:58 +0100CiaoSen(~Jura@2a05:5800:263:8800:ca4b:d6ff:fec1:99da) CiaoSen
2025-01-31 07:38:45 +0100tomboy64(~tomboy64@user/tomboy64) (Ping timeout: 248 seconds)
2025-01-31 07:40:05 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 07:42:24 +0100tomboy64(~tomboy64@user/tomboy64) tomboy64
2025-01-31 07:42:25 +0100tv(~tv@user/tv) (Read error: Connection reset by peer)
2025-01-31 07:45:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 07:47:37 +0100 <euouae> heh, cool. I didn't expect to use the State monad so soon after I learned about it but the leetcode problem needed a list of primes
2025-01-31 07:47:44 +0100 <euouae> and I implemented eratosthenes sieve: <https://paste.tomsmeding.com/vm6F8jXA>
2025-01-31 07:48:19 +0100 <euouae> I'm happy with how this turned out, looks very natural
2025-01-31 07:48:36 +0100 <euouae> I couldn't figure out if it could be done with list comprehension
2025-01-31 07:52:03 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 07:54:35 +0100 <ski> cycle [x] = repeat x
2025-01-31 07:54:59 +0100 <ski> you could just pass on the filtered list in an accumulator parameter of a recursive function
2025-01-31 07:55:28 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 08:01:09 +0100AlexNoo_(~AlexNoo@5.139.233.186)
2025-01-31 08:02:00 +0100AlexZenon(~alzenon@178.34.150.8) (Ping timeout: 246 seconds)
2025-01-31 08:02:12 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 252 seconds)
2025-01-31 08:03:19 +0100AlexNoo(~AlexNoo@178.34.150.8) (Ping timeout: 260 seconds)
2025-01-31 08:05:23 +0100 <euouae> that's true, but then how do you produce the infinite list? like (x : f rest)?
2025-01-31 08:06:03 +0100AlexZenon(~alzenon@5.139.233.186)
2025-01-31 08:07:58 +0100 <dminuoso> euouae │ why is `State s a` but `state :: a -> (a, s)`? the order is reversed
2025-01-31 08:08:05 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 08:08:29 +0100 <dminuoso> The type order is often influenced by typeclasses you want to satisfy.
2025-01-31 08:08:47 +0100 <euouae> right, for State. but why state?
2025-01-31 08:09:23 +0100 <dminuoso> So consider `instance Functor (State s)`, we cannot write `instance Functor (State _ a)`, so we reorder the types accordingly.
2025-01-31 08:09:40 +0100 <dminuoso> Sorry, that second one should have read `instance Functor (State _ s)`
2025-01-31 08:10:20 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 08:10:20 +0100 <dminuoso> euouae: So the order of arguments usually follows convenience with related functions.
2025-01-31 08:10:27 +0100 <dminuoso> And that can be quite subjective
2025-01-31 08:10:54 +0100 <dminuoso> Say you envision `state` to be used with `fmap` to map over the *state*, because that's how you (the author) like to use it, and assume others to frequently use it too.
2025-01-31 08:12:24 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 08:12:31 +0100 <dminuoso> Since fmap on a 2-tuple maps over the second argument (which too has to do with the fact that we cant just have `instance Functor (a,)` but are forced to have `instance Functor (a,)` if we were allowed to write sections in type (we have to specify write it as `instance Functor ((,) a) in reality)
2025-01-31 08:13:22 +0100 <euouae> I'm actually not sure what fmap with state does, I'd have to think about it
2025-01-31 08:13:29 +0100 <euouae> but OK if fmap is one of the reasons then I can see it
2025-01-31 08:13:48 +0100 <dminuoso> Im not sure whether that was actually the reason, keep that in mind.
2025-01-31 08:14:20 +0100 <dminuoso> euouae: One other fact that often influence parameter order, is which parameters you expect to be partially applied.
2025-01-31 08:15:01 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 248 seconds)
2025-01-31 08:15:33 +0100 <dminuoso> Say if you have `f :: S -> T -> A -> X`, and for some reason its likely you or other users will use it as `x (f s t)`, this is far more comfortable than writing `x (\a -> f a s t)`, so you turn things around to enable more point-free notation
2025-01-31 08:15:41 +0100 <glguy> The order is forced because it is intended to be a Monad
2025-01-31 08:15:54 +0100 <dminuoso> glguy: They meant why `state :: a -> (a, s)` in particular.
2025-01-31 08:16:10 +0100anpad(~pandeyan@user/anpad) (Client Quit)
2025-01-31 08:16:45 +0100 <glguy> The tuple order? There's no reason one way or the other and you can find implementations using both
2025-01-31 08:17:09 +0100 <dminuoso> Yeah. I guess no reason is also possible.
2025-01-31 08:17:10 +0100 <ski> euouae : "like (x : f rest)?" -- yes
2025-01-31 08:18:43 +0100 <dminuoso> glguy: In my experience the tuple order is usually picked based on how the author use fmap or sections with those tuples.
2025-01-31 08:18:53 +0100 <dminuoso> Which can be very subjective, still.
2025-01-31 08:20:01 +0100 <euouae> ski, isn't that less efficient?
2025-01-31 08:20:08 +0100 <ski> than what ?
2025-01-31 08:20:57 +0100 <euouae> than what I have, doesn't it get into N levels of stack frames?
2025-01-31 08:21:17 +0100 <ski> dunno what you mean
2025-01-31 08:21:21 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 08:21:55 +0100 <ski> but doing `f ... = x : f (...)' is in general not inherently inefficient
2025-01-31 08:22:03 +0100 <dminuoso> In Haskell, anyway.
2025-01-31 08:22:14 +0100 <dminuoso> Or GHC Haskell, one should say.
2025-01-31 08:22:18 +0100 <euouae> I don't know how evaluation works in Haskell well enough to understand that, but (x : f rest) is not tail-called, right? It must have O(n) memory for n steps
2025-01-31 08:22:34 +0100 <euouae> on top of the O(n) for the list itself, so arguably doesn't matter
2025-01-31 08:22:34 +0100 <ski> it'll produce the result `x', and then, if you decide to ask for more elements, only then will the recursive call computation happen
2025-01-31 08:22:54 +0100 <dminuoso> euouae: In GHC Haskell, evaluation model works vastly different from traditional programming languages. We dont exactly push to a stack at the beginning of a function and pop at the end.
2025-01-31 08:22:55 +0100 <ski> it's incremental, rather than tail-calling
2025-01-31 08:23:21 +0100 <euouae> dminuoso: is there hope to understand it for non experts or is it too difficult?
2025-01-31 08:23:39 +0100 <ski> think of the list generated as an iterator, if you like
2025-01-31 08:23:58 +0100 <ski> the caller controls how much of it is materialized
2025-01-31 08:24:03 +0100 <euouae> Oh I understand that much (i.e. what you explained here ski), but in general to understand the Haskell evaluation
2025-01-31 08:24:13 +0100 <euouae> i.e. what happens under the hood via ghc
2025-01-31 08:24:32 +0100 <dminuoso> euouae: Imagine the program was kept *textually* as you wrote it, and evaluation is just substitution.
2025-01-31 08:24:42 +0100 <ski> GHC does lazy evaulation, meaning demand-driven, with caching of intermediate results
2025-01-31 08:25:00 +0100 <euouae> What does caching mean?
2025-01-31 08:25:31 +0100 <euouae> Why would it remember intermediate results? for what purpose?
2025-01-31 08:25:41 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 08:25:42 +0100 <dminuoso> Consider `let x = <expensive computation> in (x, x)`
2025-01-31 08:25:54 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 08:26:07 +0100monochrm(trebla@216.138.220.146)
2025-01-31 08:26:09 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 248 seconds)
2025-01-31 08:26:21 +0100 <euouae> okay right. hm...
2025-01-31 08:26:24 +0100monochrmmonochrom
2025-01-31 08:26:48 +0100 <ski> it means that in `let x = 2 * 2 in x + x', first the `x + x' starts to happen, then that demands the result of `x', so `2 * 2' happens, result `4'. now it *remembers* (caches) that `x' resulted in `4', so that when the second `x' in `x + x' is checked, it reuses the `4', to compute `4 + 4', rather than performing the multiplication twice
2025-01-31 08:27:05 +0100 <euouae> so about laziness, how exactly is it accomplished in ghc?
2025-01-31 08:27:21 +0100 <euouae> does it keep track of the source code instead of computing it? and just computes when necessary?
2025-01-31 08:27:22 +0100 <ski> same thing happens, if you define `f x = x + x', and then call `f (2 * 2)'
2025-01-31 08:27:44 +0100 <ski> "does it keep track of the source code" -- no
2025-01-31 08:27:51 +0100 <dminuoso> euouae: No, we encode the whole program into what we call a spineless tagless G-machine
2025-01-31 08:27:58 +0100 <dminuoso> Which is a very efficient way of programming to native code.
2025-01-31 08:28:04 +0100 <dminuoso> s/programming/translating/
2025-01-31 08:28:18 +0100 <dminuoso> euouae: Semantically you can imagine it kept the source code and just substituted.
2025-01-31 08:28:36 +0100 <dminuoso> With sharing whenever possible
2025-01-31 08:28:41 +0100 <euouae> <https://www.microsoft.com/en-us/research/wp-content/uploads/1992/04/spineless-tagless-gmachine.pdf> is a good intro to that?
2025-01-31 08:28:43 +0100 <euouae> I'm kind of curious
2025-01-31 08:28:45 +0100 <dminuoso> (Well not quite *whenever* ...)
2025-01-31 08:29:22 +0100 <dminuoso> euouae: Give it a try, and see how far you go. If your mind explodes, put the paper aside for a future read.
2025-01-31 08:29:33 +0100 <ski> @where lazy
2025-01-31 08:29:33 +0100 <lambdabot> "Lazy Evaluation of Haskell" by monochrom at <http://www.vex.net/~trebla/haskell/lazy.xhtml>; "The Incomplete Guide to Lazy Evaluation (in Haskell)" by apfelmus in 2015-03-07 at <https://apfelmus.
2025-01-31 08:29:33 +0100 <lambdabot> nfshost.com/articles/lazy-eval.html>; "Laziness, strictness, guarded recursion" by bitemyapp at <https://github.com/bitemyapp/learnhaskell/blob/master/specific_topics.md#user-content-laziness-
2025-01-31 08:29:33 +0100 <lambdabot> strictness-guarded-recursion>
2025-01-31 08:29:39 +0100 <ski> check that first
2025-01-31 08:29:47 +0100 <euouae> firstlink or all?
2025-01-31 08:30:04 +0100 <ski> first link
2025-01-31 08:30:26 +0100 <euouae> Alright, thank you. I've got some cool stuff for the days ahead.
2025-01-31 08:30:34 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 08:31:23 +0100 <dminuoso> euouae: Ultimately we can achieve very good performance with our approach, sometimes comparable to C++ or Rust with careful programming (though to be honest even those languages require careful treatment to obtain optimal performance). STG is *that* good.
2025-01-31 08:33:12 +0100monochrm(trebla@216.138.220.146)
2025-01-31 08:33:25 +0100 <dminuoso> (Though GHC has a lot of other tricks up its sleeve to make that possible, so its not just STG)
2025-01-31 08:35:15 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 244 seconds)
2025-01-31 08:35:15 +0100monochrmmonochrom
2025-01-31 08:37:44 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) Smiles
2025-01-31 08:40:00 +0100 <euouae> neat, it's probably beyond what I can grasp but it's probably still worth looking into
2025-01-31 08:41:03 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 08:46:21 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 276 seconds)
2025-01-31 08:49:36 +0100euouae(~euouae@user/euouae) ()
2025-01-31 08:51:27 +0100 <dminuoso> % fromIntegral (0xffffff :: Word16) :: Word8
2025-01-31 08:51:27 +0100 <yahb2> <interactive>:97:15: warning: [GHC-97441] [-Woverflowed-literals] ; Literal 16777215 is out of the Word16 range 0..65535 ; ; 255
2025-01-31 08:51:52 +0100Square(~Square@user/square) (Ping timeout: 272 seconds)
2025-01-31 08:52:03 +0100 <dminuoso> I'm staring at some Haskell code that explicitly masks with 0xff before fromIntegral, is that strictly necessary or can I rely on truncation like this?
2025-01-31 08:54:31 +0100falafel(~falafel@syn-076-093-010-089.res.spectrum.com) falafel
2025-01-31 08:56:25 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 08:58:51 +0100tnt2(~Thunderbi@user/tnt1) tnt1
2025-01-31 08:59:02 +0100tnt1(~Thunderbi@user/tnt1) (Ping timeout: 252 seconds)
2025-01-31 08:59:02 +0100tnt2tnt1
2025-01-31 09:00:02 +0100caconym(~caconym@user/caconym) (Quit: bye)
2025-01-31 09:00:41 +0100caconym(~caconym@user/caconym) caconym
2025-01-31 09:01:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-01-31 09:01:32 +0100sord937(~sord937@gateway/tor-sasl/sord937) sord937
2025-01-31 09:02:05 +0100euleritian(~euleritia@dynamic-176-006-140-003.176.6.pool.telefonica.de) (Read error: Connection reset by peer)
2025-01-31 09:02:23 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de)
2025-01-31 09:05:03 +0100ljdarj(~Thunderbi@user/ljdarj) ljdarj
2025-01-31 09:06:59 +0100rvalue(~rvalue@user/rvalue) (Read error: Connection reset by peer)
2025-01-31 09:07:30 +0100rvalue(~rvalue@user/rvalue) rvalue
2025-01-31 09:09:45 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 09:11:19 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 09:13:09 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 09:13:58 +0100sawilagar(~sawilagar@user/sawilagar) sawilagar
2025-01-31 09:14:04 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 09:15:48 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds)
2025-01-31 09:16:57 +0100eL_Bart0(eL_Bart0@dietunichtguten.org)
2025-01-31 09:21:01 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 09:23:39 +0100tcard(~tcard@2400:4051:5801:7500:cf17:befc:ff82:5303) (Quit: Leaving)
2025-01-31 09:24:38 +0100user__(~user@user/fmira) (Remote host closed the connection)
2025-01-31 09:25:18 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 09:25:37 +0100acidjnk_new3(~acidjnk@p200300d6e7283f830c2bc91cde612e63.dip0.t-ipconnect.de) acidjnk
2025-01-31 09:27:08 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 09:29:36 +0100emmanuelux(~emmanuelu@user/emmanuelux) (Quit: au revoir)
2025-01-31 09:30:48 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 09:30:58 +0100danza(~danza@user/danza) danza
2025-01-31 09:32:40 +0100Googulator(~Googulato@2a01-036d-0106-1666-e945-fd21-b920-9aa7.pool6.digikabel.hu) (Ping timeout: 240 seconds)
2025-01-31 09:36:56 +0100tcard(~tcard@2400:4051:5801:7500:cf17:befc:ff82:5303) tcard
2025-01-31 09:39:50 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 09:47:41 +0100chele(~chele@user/chele) chele
2025-01-31 09:48:10 +0100nullie(~nullie@nuremberg.nullie.name) (Read error: Connection reset by peer)
2025-01-31 09:49:54 +0100falafel(~falafel@syn-076-093-010-089.res.spectrum.com) (Ping timeout: 260 seconds)
2025-01-31 09:51:35 +0100nullie(~nullie@nuremberg.nullie.name) nullie
2025-01-31 09:54:37 +0100danz55770(~danza@user/danza) danza
2025-01-31 09:56:36 +0100danza(~danza@user/danza) (Ping timeout: 252 seconds)
2025-01-31 09:58:03 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 09:58:29 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 09:59:37 +0100danz55770(~danza@user/danza) (Remote host closed the connection)
2025-01-31 09:59:52 +0100danza(~danza@user/danza) danza
2025-01-31 09:59:55 +0100AlexNoo__(~AlexNoo@5.139.233.186)
2025-01-31 10:00:11 +0100AlexZenon_2(~alzenon@5.139.233.186)
2025-01-31 10:00:32 +0100monochrm(trebla@216.138.220.146)
2025-01-31 10:00:33 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 248 seconds)
2025-01-31 10:00:48 +0100monochrmmonochrom
2025-01-31 10:01:42 +0100AlexZenon(~alzenon@5.139.233.186) (Ping timeout: 246 seconds)
2025-01-31 10:02:45 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 10:03:06 +0100AlexNoo_(~AlexNoo@5.139.233.186) (Ping timeout: 246 seconds)
2025-01-31 10:06:07 +0100CiaoSen(~Jura@2a05:5800:263:8800:ca4b:d6ff:fec1:99da) (Ping timeout: 252 seconds)
2025-01-31 10:06:35 +0100 <c_wraith> depends on the type you're coming from, as it's going to depend on how fromInteger is implemented
2025-01-31 10:07:12 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 10:07:55 +0100nullie(~nullie@nuremberg.nullie.name) (Quit: WeeChat 4.2.2)
2025-01-31 10:11:32 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 10:11:39 +0100anpad(~pandeyan@user/anpad) (Remote host closed the connection)
2025-01-31 10:12:32 +0100Sgeo(~Sgeo@user/sgeo) (Read error: Connection reset by peer)
2025-01-31 10:17:05 +0100danza(~danza@user/danza) ()
2025-01-31 10:19:52 +0100monochrm(trebla@216.138.220.146)
2025-01-31 10:20:20 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 10:20:44 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) (Quit: ash3en)
2025-01-31 10:20:59 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 260 seconds)
2025-01-31 10:21:00 +0100monochrmmonochrom
2025-01-31 10:22:36 +0100anpad(~pandeyan@user/anpad) (Client Quit)
2025-01-31 10:24:40 +0100 <c_wraith> err. that's backwards. The type you're coming from provides the toInteger implementation, which should always be exact. fromInteger depends on the destination type.
2025-01-31 10:29:58 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 10:30:08 +0100alecs(~alecs@nat16.software.imdea.org) alecs
2025-01-31 10:35:03 +0100fp1(~Thunderbi@wireless-86-50-140-50.open.aalto.fi) fp
2025-01-31 10:36:05 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 10:39:41 +0100tzh(~tzh@c-76-115-131-146.hsd1.or.comcast.net) (Quit: zzz)
2025-01-31 10:40:06 +0100fp1(~Thunderbi@wireless-86-50-140-50.open.aalto.fi) (Ping timeout: 276 seconds)
2025-01-31 10:40:22 +0100swamp_(~zmt00@user/zmt00) zmt00
2025-01-31 10:44:00 +0100zmt01(~zmt00@user/zmt00) (Ping timeout: 276 seconds)
2025-01-31 10:44:50 +0100danza(~danza@user/danza) danza
2025-01-31 10:46:53 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 10:47:03 +0100xff0x(~xff0x@fsb6a9491c.tkyc517.ap.nuro.jp) (Ping timeout: 245 seconds)
2025-01-31 10:47:59 +0100 <tomsmeding> dminuoso: what are the source and destination types? :p
2025-01-31 10:48:17 +0100 <tomsmeding> oh the destination type is Word8? then what c_wraith said
2025-01-31 10:51:08 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 244 seconds)
2025-01-31 10:51:41 +0100econo_(uid147250@id-147250.tinside.irccloud.com) (Quit: Connection closed for inactivity)
2025-01-31 10:51:42 +0100alecs(~alecs@nat16.software.imdea.org) (Ping timeout: 252 seconds)
2025-01-31 10:57:06 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 10:59:38 +0100anpad(~pandeyan@user/anpad) (Client Quit)
2025-01-31 11:00:54 +0100kritzefitz(~kritzefit@debian/kritzefitz) kritzefitz
2025-01-31 11:03:22 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 11:07:36 +0100CiaoSen(~Jura@2a05:5800:263:8800:ca4b:d6ff:fec1:99da) CiaoSen
2025-01-31 11:24:05 +0100ubert(~Thunderbi@2a02:8109:ab8a:5a00:a8f9:39f9:ef80:a859) ubert
2025-01-31 11:35:57 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 11:39:00 +0100anpad(~pandeyan@user/anpad) (Ping timeout: 252 seconds)
2025-01-31 11:40:13 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 244 seconds)
2025-01-31 11:41:52 +0100SlackCoder(~SlackCode@64-94-63-8.ip.weststar.net.ky) SlackCoder
2025-01-31 11:43:03 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 11:46:59 +0100kmein(~weechat@user/kmein) (Quit: ciao kakao)
2025-01-31 11:47:22 +0100kmein(~weechat@user/kmein) kmein
2025-01-31 11:50:49 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 11:56:23 +0100kmein(~weechat@user/kmein) (Quit: ciao kakao)
2025-01-31 11:56:44 +0100kmein(~weechat@user/kmein) kmein
2025-01-31 12:00:15 +0100monochrm(trebla@216.138.220.146)
2025-01-31 12:01:09 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 260 seconds)
2025-01-31 12:01:09 +0100monochrmmonochrom
2025-01-31 12:03:20 +0100zmt01(~zmt00@user/zmt00) zmt00
2025-01-31 12:07:12 +0100swamp_(~zmt00@user/zmt00) (Ping timeout: 276 seconds)
2025-01-31 12:08:53 +0100mange(~user@user/mange) (Remote host closed the connection)
2025-01-31 12:12:21 +0100tv(~tv@user/tv) tv
2025-01-31 12:18:46 +0100JuanDaugherty(~juan@user/JuanDaugherty) JuanDaugherty
2025-01-31 12:21:10 +0100auri(~auri@fsf/member/auri) (Quit: No Ping reply in 210 seconds.)
2025-01-31 12:25:01 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 12:25:26 +0100ljdarj1(~Thunderbi@user/ljdarj) ljdarj
2025-01-31 12:28:30 +0100ljdarj(~Thunderbi@user/ljdarj) (Ping timeout: 252 seconds)
2025-01-31 12:28:30 +0100ljdarj1ljdarj
2025-01-31 12:29:03 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 12:37:33 +0100danza(~danza@user/danza) (Ping timeout: 252 seconds)
2025-01-31 12:37:33 +0100nckx(nckx@libera/staff/owl/nckx) (Ping timeout: 608 seconds)
2025-01-31 12:38:16 +0100ell(~ellie@user/ellie) (Quit: Ping timeout (120 seconds))
2025-01-31 12:38:34 +0100ell(~ellie@user/ellie) ellie
2025-01-31 12:38:37 +0100anpad(~pandeyan@user/anpad) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 12:44:21 +0100anpad(~pandeyan@user/anpad) anpad
2025-01-31 12:48:10 +0100troydm(~troydm@user/troydm) (Quit: What is Hope? That all of your wishes and all of your dreams come true? To turn back time because things were not supposed to happen like that (C) Rau Le Creuset)
2025-01-31 12:51:00 +0100Digit(~user@user/digit) (Ping timeout: 244 seconds)
2025-01-31 12:53:29 +0100JuanDaughertyColinRobinson
2025-01-31 12:57:05 +0100AkechiShiro(~licht@user/akechishiro) AkechiShiro
2025-01-31 12:59:21 +0100Guest64(~Guest64@2600:387:f:7e17::1)
2025-01-31 13:00:21 +0100Guest64(~Guest64@2600:387:f:7e17::1) (Client Quit)
2025-01-31 13:00:28 +0100Guest94(~Guest64@2600:387:f:7e12::b)
2025-01-31 13:04:12 +0100Guest94(~Guest64@2600:387:f:7e12::b) (Client Quit)
2025-01-31 13:04:31 +0100Guest64(~Guest64@2600:387:f:7e12::b)
2025-01-31 13:04:47 +0100jespada(~jespada@2800:a4:2213:dd00:8c24:32fa:8fb8:ea12) jespada
2025-01-31 13:05:22 +0100 <kaol> My favorite thing about ghci is :set -freverse-errors.
2025-01-31 13:10:53 +0100Guest64(~Guest64@2600:387:f:7e12::b) (Quit: Client closed)
2025-01-31 13:13:13 +0100 <merijn> kaol: That's one of my default GHC settings :p
2025-01-31 13:13:44 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 13:15:16 +0100 <haskellbridge> <sm> interesting
2025-01-31 13:15:32 +0100 <haskellbridge> <sm> why is it better ?
2025-01-31 13:15:44 +0100ColinRobinson(~juan@user/JuanDaugherty) (Quit: praxis.meansofproduction.biz (juan@acm.org))
2025-01-31 13:16:51 +0100 <kaol> Because lines earlier in a source file are more likely to cause further errors later.
2025-01-31 13:17:24 +0100 <kaol> If there are a lot of errors they have all scrolled into oblivion.
2025-01-31 13:18:14 +0100xff0x(~xff0x@ai096095.d.east.v6connect.net)
2025-01-31 13:18:19 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 13:18:41 +0100 <kaol> And the first error is going to be in a fixed place in a regular terminal. With the default I have to scan vertically to even find it.
2025-01-31 13:19:29 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 248 seconds)
2025-01-31 13:20:41 +0100monochrom(trebla@216.138.220.146)
2025-01-31 13:20:54 +0100SlackCoder(~SlackCode@64-94-63-8.ip.weststar.net.ky) (Quit: Leaving)
2025-01-31 13:20:56 +0100ft(~ft@p3e9bcd97.dip0.t-ipconnect.de) ft
2025-01-31 13:22:16 +0100__monty__(~toonn@user/toonn) toonn
2025-01-31 13:26:09 +0100L29Ah(~L29Ah@wikipedia/L29Ah) ()
2025-01-31 13:36:37 +0100monochrom(trebla@216.138.220.146) (Ping timeout: 248 seconds)
2025-01-31 13:39:27 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) (Quit: ash3en)
2025-01-31 13:40:25 +0100monochrom(trebla@216.138.220.146)
2025-01-31 13:44:40 +0100AlexNoo__AlexNoo
2025-01-31 13:48:04 +0100laxmik(~laxmik@wifi-gate-eduroam.fzu.cz) laxmik
2025-01-31 13:48:31 +0100laxmikmichals
2025-01-31 13:49:36 +0100michals(~laxmik@wifi-gate-eduroam.fzu.cz) (Client Quit)
2025-01-31 13:51:00 +0100iamsleepy(~weechat@2a01:4f9:3070:feff:a9de:dfff:cd7f:fdcd) (Read error: Connection reset by peer)
2025-01-31 13:51:25 +0100iamsleepy(~weechat@2a01:4f9:3070:feff:d8a:11d8:7a8b:29a2) iamsleepy
2025-01-31 13:51:29 +0100 <dminuoso> c_wraith, tomsmeding: Mmm okay, this is not very satisfying. The actual answer is buried behind CMM implementation details of some primops then.
2025-01-31 13:51:43 +0100 <dminuoso> Maybe I need to consult the Haskell Report.
2025-01-31 13:52:10 +0100 <dminuoso> instance Num Word8 where
2025-01-31 13:52:15 +0100 <dminuoso> fromInteger i = W8# (wordToWord8# (integerToWord# i))
2025-01-31 13:53:43 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2025-01-31 13:54:08 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) bitdex
2025-01-31 13:54:50 +0100 <haskellbridge> <sm> kaol: I can't quite relate to that. I feel the first error is more likely to be the causative one, and I am generally using either VS code or ghcid which shows it
2025-01-31 13:55:32 +0100 <dminuoso> And the Haskell Report has no guidance on the behavior of fromInteger either.
2025-01-31 13:55:40 +0100 <dminuoso> I'm not impressed.
2025-01-31 13:55:48 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4) lortabac
2025-01-31 13:56:21 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-f81b-81aa-4344-3e67.rev.sfr.net) alexherbo2
2025-01-31 13:57:16 +0100 <tomsmeding> kaol: this is what ghcid does correctly, it shows only the top screenful of errors :p
2025-01-31 14:02:30 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 14:03:34 +0100 <kaol> ghcid doesn't really fit my use patterns. Once I get it to compile I usually want to try out a few things with my new functions in the repl.
2025-01-31 14:03:58 +0100 <haskellbridge> <sm> ghcid gets its own window, of course
2025-01-31 14:04:17 +0100 <__monty__> You can invert the order of errors reported by GHC FYI.
2025-01-31 14:05:08 +0100 <geekosaur> that was what started this thread
2025-01-31 14:06:07 +0100 <__monty__> Ah, carry on.
2025-01-31 14:06:39 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 244 seconds)
2025-01-31 14:07:09 +0100 <kaol> I'm thinking of using inotify to use xdotool to send that :r up enter. Then I would have the code loaded in it already and not have to look at two windows and still do :r up enter.
2025-01-31 14:08:08 +0100 <kaol> No wait, up enter is only relevat if I use history.
2025-01-31 14:08:13 +0100 <geekosaur> that sounds like a hacky way to reinvent ghcid/ghciwatch
2025-01-31 14:08:23 +0100 <kaol> ghcid is the hack.
2025-01-31 14:09:02 +0100 <kaol> Give me something that integrates with the repl.
2025-01-31 14:14:55 +0100jespada(~jespada@2800:a4:2213:dd00:8c24:32fa:8fb8:ea12) (Ping timeout: 244 seconds)
2025-01-31 14:17:44 +0100jespada(~jespada@2800:a4:2215:4d00:20a9:6cd:d7c4:a65f) jespada
2025-01-31 14:19:59 +0100AlexZenon_2AlexZenon
2025-01-31 14:27:35 +0100 <haskellbridge> <sm> ghcid is a hack of the gods, then :)
2025-01-31 14:27:39 +0100 <haskellbridge> <sm> love it
2025-01-31 14:28:25 +0100 <haskellbridge> <sm> kaol: you might like this small improvement in .ghci, I find it very useful:
2025-01-31 14:28:25 +0100 <haskellbridge> ... long message truncated: https://kf8nh.com/_heisenbridge/media/kf8nh.com/sCYnuCtwPTknTRbDePLKlYOX/yxjBbcu9HSA (3 lines)
2025-01-31 14:29:01 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-f81b-81aa-4344-3e67.rev.sfr.net) (Remote host closed the connection)
2025-01-31 14:29:15 +0100 <haskellbridge> <sm> it means I can just CTRL-p, enter after a change
2025-01-31 14:29:52 +0100 <haskellbridge> <sm> or up enter, as you say
2025-01-31 14:30:24 +0100p3n(~p3n@2a00:19a0:3:7c:0:d9c6:7cf6:1) (Quit: ZNC 1.9.1 - https://znc.in)
2025-01-31 14:31:14 +0100CiaoSen(~Jura@2a05:5800:263:8800:ca4b:d6ff:fec1:99da) (Ping timeout: 260 seconds)
2025-01-31 14:31:30 +0100 <haskellbridge> <sm> what about https://hackage.haskell.org/package/rapid-0.1.5.3/docs/Rapid.html
2025-01-31 14:31:52 +0100swamp_(~zmt00@user/zmt00) zmt00
2025-01-31 14:32:24 +0100tabaqui1(~root@87.200.129.102) tabaqui
2025-01-31 14:35:19 +0100zmt01(~zmt00@user/zmt00) (Ping timeout: 260 seconds)
2025-01-31 14:36:48 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2025-01-31 14:42:35 +0100johnjaye(~pi@syn-035-146-235-019.res.spectrum.com) (Read error: Connection reset by peer)
2025-01-31 14:44:59 +0100johnjaye(~pi@syn-035-146-235-019.res.spectrum.com) johnjaye
2025-01-31 14:45:41 +0100hughjfch1(~hughjfche@vmi2417424.contaboserver.net) (Quit: WeeChat 4.4.3)
2025-01-31 14:46:16 +0100hughjfch1(~hughjfche@vmi2417424.contaboserver.net) hughjfchen
2025-01-31 14:50:53 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 14:50:59 +0100weary-traveler(~user@user/user363627) user363627
2025-01-31 14:55:12 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:55ab:e185:7f81:54a4) (Quit: WeeChat 4.4.2)
2025-01-31 14:55:21 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 14:57:45 +0100machinedgod(~machinedg@d108-173-18-100.abhsia.telus.net) machinedgod
2025-01-31 14:59:45 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Quit: = "")
2025-01-31 15:02:50 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-8987-9b89-16c5-ba01.rev.sfr.net) alexherbo2
2025-01-31 15:03:08 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) Smiles
2025-01-31 15:04:18 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de)
2025-01-31 15:12:17 +0100alp(~alp@2001:861:8ca0:4940:465c:30a2:2211:b30f) (Ping timeout: 252 seconds)
2025-01-31 15:14:19 +0100pavonia(~user@user/siracusa) siracusa
2025-01-31 15:19:08 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-8987-9b89-16c5-ba01.rev.sfr.net) (Remote host closed the connection)
2025-01-31 15:22:23 +0100alp(~alp@2001:861:8ca0:4940:6044:ccfa:bd56:f4d9)
2025-01-31 15:27:19 +0100acidjnk_new3(~acidjnk@p200300d6e7283f830c2bc91cde612e63.dip0.t-ipconnect.de) (Ping timeout: 252 seconds)
2025-01-31 15:27:33 +0100acidjnk_new3(~acidjnk@p200300d6e7283f83edaedff6126e1841.dip0.t-ipconnect.de)
2025-01-31 15:29:06 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 15:31:44 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-8987-9b89-16c5-ba01.rev.sfr.net) alexherbo2
2025-01-31 15:33:25 +0100p3n(~p3n@217.198.124.246) p3n
2025-01-31 15:34:38 +0100alp(~alp@2001:861:8ca0:4940:6044:ccfa:bd56:f4d9) (Remote host closed the connection)
2025-01-31 15:35:01 +0100alp(~alp@2001:861:8ca0:4940:54fd:6cb8:585b:9cc)
2025-01-31 15:36:49 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de) (Quit: Client closed)
2025-01-31 15:39:21 +0100alp(~alp@2001:861:8ca0:4940:54fd:6cb8:585b:9cc) (Ping timeout: 252 seconds)
2025-01-31 15:39:38 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 15:42:17 +0100Sgeo(~Sgeo@user/sgeo) Sgeo
2025-01-31 15:44:10 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 272 seconds)
2025-01-31 15:54:07 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-8987-9b89-16c5-ba01.rev.sfr.net) (Remote host closed the connection)
2025-01-31 16:04:19 +0100Guest33(~Guest33@151.73.135.114)
2025-01-31 16:04:47 +0100Guest33(~Guest33@151.73.135.114) (Client Quit)
2025-01-31 16:06:34 +0100Putonlalla(~Putonlall@it-cyan.it.jyu.fi) (Quit: Leaving.)
2025-01-31 16:07:27 +0100slack1256(~slack1256@179.60.70.224) slack1256
2025-01-31 16:12:19 +0100zmt01(~zmt00@user/zmt00) zmt00
2025-01-31 16:12:56 +0100 <slack1256> I have a codebase that uses implicit parameters with mutable variables (think queues). I want to migrate to effectful. The migration is happening all at once, I create a static effect per implicit parameter and I create a function like `withDB` to scope the blocks that require that parameter. Implicit parameter resist being constraints on instance heads, so I cannot define classes to have two versions of each function. What alternatives do I have to ab
2025-01-31 16:12:56 +0100 <slack1256> stract over implicit parameters?
2025-01-31 16:13:03 +0100johnjaye(~pi@syn-035-146-235-019.res.spectrum.com) (Quit: WeeChat 4.0.0-dev)
2025-01-31 16:14:32 +0100 <dminuoso> slack1256: Can you elaborate on "Implicit parameter resist being constraints on instance heads, so I cannot define classes to have two versions of each function", perhaps with a code example?
2025-01-31 16:15:10 +0100 <slack1256> dminuoso: Sure, give me a moment.
2025-01-31 16:15:29 +0100swamp_(~zmt00@user/zmt00) (Ping timeout: 260 seconds)
2025-01-31 16:16:38 +0100zmt01(~zmt00@user/zmt00) (Ping timeout: 244 seconds)
2025-01-31 16:16:48 +0100 <geekosaur> "You can’t have an implicit parameter in the context of a class or instance declaration." (https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/implicit_parameters.html#implicit-p…)
2025-01-31 16:17:51 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de) (Ping timeout: 252 seconds)
2025-01-31 16:18:12 +0100euleritian(~euleritia@dynamic-176-006-142-115.176.6.pool.telefonica.de)
2025-01-31 16:22:42 +0100 <slack1256> https://pastebin.com/zX9KcNQu dminuoso
2025-01-31 16:24:51 +0100 <dminuoso> slack1256: The thing I dont quite understand, are you not trying to migrate away from implicit parameters?
2025-01-31 16:27:02 +0100 <slack1256> dminuoso: too much code already uses it on the codebase. We are in a middle of a sprint and other developers are making changes to their own modules. Changing them all in a big PR would cause a lot of conflicts when trying to merge.
2025-01-31 16:28:57 +0100 <dminuoso> slack1256: Its hard to tell without a bit more context, unsure whether the example is contrived or whether this is truly just about database connection strings
2025-01-31 16:29:04 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 16:29:44 +0100 <geekosaur> tbh if you're using an effect system, its state abstraction is an IORef (because effect systems are fancy ReaderT, more or less) and switching to that is the saner option than implicit params anyway
2025-01-31 16:29:59 +0100 <geekosaur> I don't think I've ever seen a use for implicit params that waasn't better served some other way
2025-01-31 16:30:13 +0100 <geekosaur> and they break reasoning about code
2025-01-31 16:33:15 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 16:33:28 +0100 <dminuoso> slack1256: That said, Im not entirely sure you need any partial solution here. During migration you can also just have *both* some effect and an implicit parameter, just make sure you resolve them coherently until the implicit params are gone.
2025-01-31 16:33:46 +0100 <dminuoso> So some parts just use the effect, others use implicit params.
2025-01-31 16:34:08 +0100 <dminuoso> It's certainly not ideal, but no migration ever was.
2025-01-31 16:36:04 +0100 <slack1256> dminuoso: "Resolve them coherently" is the problem, I have to do it by hand instaed of using typeclasses. I have to duplicate the callers of those functions, the different constraints bubble up. If I could abstract over implicit parameters with classes I could delegate this to the compiler to choose the right calling convention.
2025-01-31 16:36:30 +0100L29Ah(~L29Ah@wikipedia/L29Ah) L29Ah
2025-01-31 16:36:37 +0100 <dminuoso> slack1256: Again, hard to say without knowing more about your code - but ideally there wouldnt be many places where you resolve effects.
2025-01-31 16:36:50 +0100 <dminuoso> Hard to imagine why there would be more than one.
2025-01-31 16:36:57 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de)
2025-01-31 16:37:08 +0100Guest37(~Guest62@c-73-217-79-154.hsd1.co.comcast.net)
2025-01-31 16:39:15 +0100hueso(~root@user/hueso) (Quit: No Ping reply in 180 seconds.)
2025-01-31 16:41:24 +0100hueso(~root@user/hueso) hueso
2025-01-31 16:43:05 +0100GoldsteinQ(~goldstein@goldstein.rs) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 16:44:24 +0100ystael_(~ystael@user/ystael) (Quit: Lost terminal)
2025-01-31 16:45:18 +0100vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2025-01-31 16:46:20 +0100ystael(~ystael@user/ystael) ystael
2025-01-31 16:46:28 +0100GoldsteinQ(~goldstein@goldstein.rs)
2025-01-31 16:49:18 +0100L29Ah(~L29Ah@wikipedia/L29Ah) ()
2025-01-31 16:53:05 +0100L29Ah(~L29Ah@wikipedia/L29Ah) L29Ah
2025-01-31 16:54:42 +0100acidjnk_new3(~acidjnk@p200300d6e7283f83edaedff6126e1841.dip0.t-ipconnect.de) (Ping timeout: 252 seconds)
2025-01-31 16:57:50 +0100 <ski> slack1256 : constraint synonyms ?
2025-01-31 17:00:39 +0100GoldsteinQ(~goldstein@goldstein.rs) (Quit: ZNC 1.8.2 - https://znc.in)
2025-01-31 17:03:20 +0100GoldsteinQ(~goldstein@goldstein.rs)
2025-01-31 17:03:31 +0100euleritian(~euleritia@dynamic-176-006-142-115.176.6.pool.telefonica.de) (Read error: Connection reset by peer)
2025-01-31 17:03:49 +0100euleritian(~euleritia@ip4d17fae8.dynamic.kabel-deutschland.de)
2025-01-31 17:05:04 +0100 <slack1256> ski: Even with -XConstraintKinds we cannot use implicit parameters on instance heads...
2025-01-31 17:07:57 +0100 <ski> hm, i see
2025-01-31 17:09:10 +0100Guest37(~Guest62@c-73-217-79-154.hsd1.co.comcast.net) (Ping timeout: 240 seconds)
2025-01-31 17:09:41 +0100 <ski> hm, looks like `data Dict_XInt = (x :: Int) => WrapXInt' works, and i suppose one could then try `class XInt where xInt :: Dict_XInt' .. hmmm
2025-01-31 17:10:15 +0100 <ski> (or `xInt :: ((x :: Int) -> o) -> o', skipping `Dict_XInt')
2025-01-31 17:10:46 +0100 <ski> (ah .. `xInt :: ((x :: Int) => o) -> o')
2025-01-31 17:15:15 +0100Guest87(~Guest92@14.194.140.178)
2025-01-31 17:19:28 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 17:22:06 +0100RMSBach(~guygastin@137.184.131.156) (Ping timeout: 252 seconds)
2025-01-31 17:23:30 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 244 seconds)
2025-01-31 17:27:26 +0100zmt00(~zmt00@user/zmt00) zmt00
2025-01-31 17:30:26 +0100Digit(~user@user/digit) Digit
2025-01-31 17:31:46 +0100ubert(~Thunderbi@2a02:8109:ab8a:5a00:a8f9:39f9:ef80:a859) (Ping timeout: 244 seconds)
2025-01-31 17:32:28 +0100zmt00(~zmt00@user/zmt00) (Ping timeout: 272 seconds)
2025-01-31 17:34:03 +0100Square(~Square@user/square) Square
2025-01-31 17:35:24 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) (Ping timeout: 260 seconds)
2025-01-31 17:35:41 +0100ash3en(~Thunderbi@146.70.124.222) ash3en
2025-01-31 17:36:52 +0100EvanR(~EvanR@user/evanr) (Quit: Leaving)
2025-01-31 17:38:14 +0100EvanR(~EvanR@user/evanr) EvanR
2025-01-31 17:41:28 +0100ash3en1(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 17:43:14 +0100ash3en(~Thunderbi@146.70.124.222) (Ping timeout: 272 seconds)
2025-01-31 17:43:14 +0100ash3en1ash3en
2025-01-31 17:45:05 +0100Guest87(~Guest92@14.194.140.178) (Quit: Client closed)
2025-01-31 17:46:19 +0100sp1ff(~user@c-67-160-173-55.hsd1.wa.comcast.net) (Read error: Connection reset by peer)
2025-01-31 17:48:29 +0100alp(~alp@2001:861:8ca0:4940:291:464f:2c61:f1c2)
2025-01-31 17:57:36 +0100lxsameer(~lxsameer@Serene/lxsameer) lxsameer
2025-01-31 17:58:16 +0100 <lxsameer> hey folks, how can I define a type alias for `(Foo x y) => x -> (x y, y)` type?
2025-01-31 18:00:23 +0100 <merijn> lxsameer: Generally you'd keep the constraint out of the alias
2025-01-31 18:01:00 +0100 <merijn> lxsameer: Because otherwise you're (intentionally or not) defining an existential
2025-01-31 18:01:09 +0100 <merijn> eh, not existential
2025-01-31 18:01:17 +0100 <merijn> rankn type, I meant
2025-01-31 18:02:09 +0100 <lxsameer> merijn: ok i have to read more about it then
2025-01-31 18:02:11 +0100 <lxsameer> thank you
2025-01-31 18:02:55 +0100peterbecich(~Thunderbi@syn-047-229-123-186.res.spectrum.com) peterbecich
2025-01-31 18:06:18 +0100ubert(~Thunderbi@p200300ecdf4e6362e6b318fffe838f33.dip0.t-ipconnect.de) ubert
2025-01-31 18:06:48 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2025-01-31 18:08:12 +0100 <c_wraith> unless you have deep subsumption enabled, in which case it implicitly lifts the constraint to the top of the type
2025-01-31 18:08:51 +0100 <c_wraith> I still can't believe that was GHC's default behavior for forever.
2025-01-31 18:09:12 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 18:11:21 +0100 <lxsameer> thank you
2025-01-31 18:12:48 +0100ubert(~Thunderbi@p200300ecdf4e6362e6b318fffe838f33.dip0.t-ipconnect.de) (Ping timeout: 252 seconds)
2025-01-31 18:13:29 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 260 seconds)
2025-01-31 18:13:48 +0100ubert(~Thunderbi@p200300ecdf4e6362e6fd4bc8009ee988.dip0.t-ipconnect.de) ubert
2025-01-31 18:14:33 +0100chele(~chele@user/chele) (Remote host closed the connection)
2025-01-31 18:14:54 +0100machinedgod(~machinedg@d108-173-18-100.abhsia.telus.net) (Ping timeout: 252 seconds)
2025-01-31 18:15:14 +0100 <ski> "you're (intentionally or not) defining an existential" -- unless you parameterize
2025-01-31 18:17:51 +0100ljdarj(~Thunderbi@user/ljdarj) (Ping timeout: 265 seconds)
2025-01-31 18:17:54 +0100 <ski> (iow, `type Blah x y = Foo x y => x -> (x y,y)' .. still, it's not too clear how useful this would be)
2025-01-31 18:18:12 +0100 <ski> .. it seems like it would perhaps be useful to be able to declare a constraint as a presupposition of a synonym
2025-01-31 18:19:04 +0100 <ski> type Foo x y => Blah x y = x -> (x y,y) -- if `Foo x y' holds, then `Blah x y' is an alias for `(x y,y)'
2025-01-31 18:21:12 +0100 <ski> therefore `Blah x y -> Blah x y' means `(x -> (x y,y)) -> (x -> (x y,y))' with `Foo x y' as presupposition, so if that's the inferred type of a function binding, it'd get (assuming no further constraints on `x' and `y' generalized to `forall x y. Blah x y => (x -> (x y,y)) -> (x -> (x y,y))
2025-01-31 18:21:17 +0100 <ski> '
2025-01-31 18:22:23 +0100 <ski> er, s/Blah x y =>/Foo x y =>/
2025-01-31 18:22:42 +0100 <ski> (if you'd use an explicit type signature, you'd still need to include the constraint `Foo x y' in `frob :: Foo x y => Blah x y -> Blah x y'
2025-01-31 18:23:08 +0100 <ski> )
2025-01-31 18:23:09 +0100 <ski> c_wraith : hm, subsumption worked something like the above ?
2025-01-31 18:28:54 +0100machinedgod(~machinedg@d108-173-18-100.abhsia.telus.net) machinedgod
2025-01-31 18:33:30 +0100 <EvanR> s/Blah/Foo, s/Foo/Blah, Blarg!
2025-01-31 18:33:47 +0100acidjnk_new3(~acidjnk@p200300d6e7283f83f8f1a3a9ad07643b.dip0.t-ipconnect.de) acidjnk
2025-01-31 18:34:08 +0100urdh(~urdh@user/urdh) (Ping timeout: 245 seconds)
2025-01-31 18:34:31 +0100ljdarj(~Thunderbi@user/ljdarj) ljdarj
2025-01-31 18:39:09 +0100ensyde(~ensyde@2601:5c6:c200:6dc0::64a2) (Ping timeout: 260 seconds)
2025-01-31 18:48:21 +0100target_i(~target_i@user/target-i/x-6023099) target_i
2025-01-31 18:51:12 +0100peterbecich(~Thunderbi@syn-047-229-123-186.res.spectrum.com) (Ping timeout: 252 seconds)
2025-01-31 18:51:12 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) (Quit: ash3en)
2025-01-31 18:52:20 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 18:54:37 +0100sord937(~sord937@gateway/tor-sasl/sord937) (Quit: sord937)
2025-01-31 18:56:30 +0100jespada(~jespada@2800:a4:2215:4d00:20a9:6cd:d7c4:a65f) (Quit: My Mac has gone to sleep. ZZZzzz…)
2025-01-31 18:57:21 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) (Ping timeout: 276 seconds)
2025-01-31 18:57:28 +0100ash3en1(~Thunderbi@146.70.124.222) ash3en
2025-01-31 18:58:06 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de) (Quit: Client closed)
2025-01-31 18:58:37 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 18:58:49 +0100tabaqui1(~root@87.200.129.102) (Ping timeout: 260 seconds)
2025-01-31 18:59:47 +0100ash3en1ash3en
2025-01-31 19:00:32 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de)
2025-01-31 19:01:01 +0100L29Ah(~L29Ah@wikipedia/L29Ah) (Quit: Gateway shutdown)
2025-01-31 19:02:48 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 19:05:34 +0100jespada(~jespada@2800:a4:2215:4d00:20a9:6cd:d7c4:a65f) jespada
2025-01-31 19:10:16 +0100Pozyomka_(~pyon@user/pyon) (Quit: WeeChat 4.5.1)
2025-01-31 19:12:36 +0100ash3en(~Thunderbi@146.70.124.222) (Ping timeout: 246 seconds)
2025-01-31 19:14:29 +0100Pozyomka(~pyon@user/pyon) pyon
2025-01-31 19:16:34 +0100L29Ah(~L29Ah@wikipedia/L29Ah) L29Ah
2025-01-31 19:18:50 +0100Lord_of_Life(~Lord@user/lord-of-life/x-2819915) (Read error: Connection reset by peer)
2025-01-31 19:22:23 +0100Lord_of_Life(~Lord@user/lord-of-life/x-2819915) Lord_of_Life
2025-01-31 19:27:09 +0100tzh(~tzh@c-76-115-131-146.hsd1.or.comcast.net) tzh
2025-01-31 19:27:43 +0100Lord_of_Life(~Lord@user/lord-of-life/x-2819915) (Excess Flood)
2025-01-31 19:28:03 +0100gehmehgeh(~user@user/gehmehgeh) gehmehgeh
2025-01-31 19:28:13 +0100Lord_of_Life(~Lord@user/lord-of-life/x-2819915) Lord_of_Life
2025-01-31 19:28:40 +0100gmg(~user@user/gehmehgeh) (Remote host closed the connection)
2025-01-31 19:32:13 +0100ozkutuk(~ozkutuk@24.133.86.69) ozkutuk
2025-01-31 19:35:24 +0100vektor(~vektor@IP-149249154134.pools.medianet-world.de) (Quit: Client closed)
2025-01-31 19:42:38 +0100slack1256(~slack1256@179.60.70.224) (Remote host closed the connection)
2025-01-31 19:47:41 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 19:48:35 +0100Smiles(uid551636@id-551636.lymington.irccloud.com) Smiles
2025-01-31 19:52:04 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 252 seconds)
2025-01-31 19:53:56 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-5d7d-beeb-ea7b-ad40.rev.sfr.net) alexherbo2
2025-01-31 19:53:56 +0100MyNetAz(~MyNetAz@user/MyNetAz) (Read error: Connection reset by peer)
2025-01-31 19:57:09 +0100lxsameer(~lxsameer@Serene/lxsameer) (Ping timeout: 260 seconds)
2025-01-31 19:58:46 +0100L29Ah(~L29Ah@wikipedia/L29Ah) ()
2025-01-31 20:00:57 +0100MyNetAz(~MyNetAz@user/MyNetAz) MyNetAz
2025-01-31 20:01:28 +0100TheCoffeMaker(~TheCoffeM@user/thecoffemaker) (Remote host closed the connection)
2025-01-31 20:01:51 +0100TheCoffeMaker(~TheCoffeM@user/thecoffemaker) TheCoffeMaker
2025-01-31 20:02:03 +0100dsrt^(~dsrt@108.192.66.114)
2025-01-31 20:03:06 +0100alexherbo2(~alexherbo@2a02-8440-3504-8116-5d7d-beeb-ea7b-ad40.rev.sfr.net) (Remote host closed the connection)
2025-01-31 20:08:12 +0100alexherbo2(~alexherbo@2a02-8440-3503-94e0-1866-04f2-f81a-c1ec.rev.sfr.net) alexherbo2
2025-01-31 20:10:09 +0100ncf(~n@monade.li) (Quit: Fairfarren.)
2025-01-31 20:10:25 +0100ncf(~n@monade.li) ncf
2025-01-31 20:10:39 +0100jespada(~jespada@2800:a4:2215:4d00:20a9:6cd:d7c4:a65f) (Quit: Textual IRC Client: www.textualapp.com)
2025-01-31 20:11:36 +0100Guest39(~Guest39@cpc1-lich12-2-0-cust2633.3-2.cable.virginm.net)
2025-01-31 20:17:53 +0100jespada(~jespada@2800:a4:2215:4d00:9c45:c000:6937:52ff) jespada
2025-01-31 20:18:01 +0100jespada(~jespada@2800:a4:2215:4d00:9c45:c000:6937:52ff) (Client Quit)
2025-01-31 20:30:17 +0100vanishingideal(~vanishing@user/vanishingideal) (Ping timeout: 265 seconds)
2025-01-31 20:31:43 +0100vanishingideal(~vanishing@user/vanishingideal) vanishingideal
2025-01-31 20:32:46 +0100ash3en(~Thunderbi@2a03:7846:b6eb:101:93ac:a90a:da67:f207) ash3en
2025-01-31 20:33:37 +0100L29Ah(~L29Ah@wikipedia/L29Ah) L29Ah
2025-01-31 20:39:06 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 20:43:15 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 246 seconds)
2025-01-31 20:47:54 +0100weary-traveler(~user@user/user363627) (Remote host closed the connection)
2025-01-31 20:48:55 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds)
2025-01-31 20:58:49 +0100gehmehgehgmg
2025-01-31 21:00:04 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 21:00:07 +0100caconym(~caconym@user/caconym) (Quit: bye)
2025-01-31 21:00:44 +0100caconym(~caconym@user/caconym) caconym
2025-01-31 21:01:42 +0100euouae(~euouae@user/euouae) euouae
2025-01-31 21:02:55 +0100 <euouae> I've been reading <https://www.vex.net/~trebla/haskell/lazy.xhtml> and what seems to me is that lazy evaluation in Haskell means that expressions are only evaluated enough to match patterns & guards
2025-01-31 21:03:07 +0100 <euouae> Is that an accurate understanding?
2025-01-31 21:05:17 +0100Guest39(~Guest39@cpc1-lich12-2-0-cust2633.3-2.cable.virginm.net) (Quit: Client closed)
2025-01-31 21:06:41 +0100 <mauke> probably also to lambda form for function application
2025-01-31 21:06:59 +0100 <mauke> can't f x if f is still thunk
2025-01-31 21:07:05 +0100 <euouae> Yeah I was thinking that also in terms of pattern matching too, is that wrong?
2025-01-31 21:07:36 +0100 <euouae> e.g. `(\c _ -> c) 0 missiles` does not evaluate missiles because it fits into the hole
2025-01-31 21:08:19 +0100 <Rembane> > (\c _ -> c) 0 undefined
2025-01-31 21:08:20 +0100 <lambdabot> 0
2025-01-31 21:08:34 +0100 <mauke> > undefined 42
2025-01-31 21:08:35 +0100 <lambdabot> *Exception: Prelude.undefined
2025-01-31 21:08:50 +0100 <mauke> I don't think there's any pattern matching here
2025-01-31 21:09:09 +0100 <euouae> Oh you're saying `f` itself is lazily evaluated until a lambda form is exposed
2025-01-31 21:09:25 +0100 <mauke> yes
2025-01-31 21:09:37 +0100 <euouae> ah, thank you...
2025-01-31 21:10:07 +0100 <mauke> otherwise lazy lambda calculus would never get anything done :-)
2025-01-31 21:10:21 +0100 <Rembane> > (\(x:_) -> x) [0, undefined]
2025-01-31 21:10:23 +0100 <lambdabot> 0
2025-01-31 21:11:45 +0100 <mauke> oh, and there's a subtlety with newtype constructor patterns
2025-01-31 21:12:23 +0100 <mauke> newtype Identity a = Identity a; ... case undefined of { Identity _ -> () } -- evaluates to ()
2025-01-31 21:12:46 +0100 <mauke> even though it looks like we're matching on a constructor
2025-01-31 21:12:55 +0100 <euouae> The subtlety is that newtype always matches?
2025-01-31 21:13:08 +0100 <euouae> the article I linked above mentioned that newtype is an exception but did not say yet why
2025-01-31 21:13:27 +0100 <mauke> at runtime, newtype patterns are no-ops
2025-01-31 21:13:42 +0100 <mauke> since there's only one possible constructor, it has no representation at all
2025-01-31 21:14:33 +0100 <mauke> .oO( and cannot be taxed )
2025-01-31 21:15:15 +0100 <euouae> rebel newtype
2025-01-31 21:16:46 +0100 <mauke> > case undefined of { Identity _ -> () }
2025-01-31 21:16:48 +0100 <lambdabot> ()
2025-01-31 21:16:59 +0100 <mauke> > Just undefined `seq` ()
2025-01-31 21:17:00 +0100 <lambdabot> ()
2025-01-31 21:17:06 +0100 <mauke> > Identity undefined `seq` ()
2025-01-31 21:17:07 +0100 <lambdabot> *Exception: Prelude.undefined
2025-01-31 21:18:50 +0100Guest74(~Guest74@81-231-8-142-no600.tbcn.telia.com)
2025-01-31 21:20:01 +0100 <euouae> I don't exactly understand how sharing works, does GHC remember an expression?
2025-01-31 21:20:16 +0100 <euouae> I mean, in formal lazy evaluation, what exactly is sharing?
2025-01-31 21:20:22 +0100 <dminuoso> euouae: Have you seen any of the guides that include visualizations?
2025-01-31 21:20:55 +0100 <euouae> I guess I'm realizing that it's impossible to share between two different scopes
2025-01-31 21:20:59 +0100 <dminuoso> euouae: So sharing itself is implemented by just pointers pointing to the same thunk.
2025-01-31 21:21:10 +0100wootehfoot(~wootehfoo@user/wootehfoot) wootehfoot
2025-01-31 21:21:11 +0100 <dminuoso> Literally to the same address in memory
2025-01-31 21:21:16 +0100 <euouae> Or is sharing happening between two different scopes too?
2025-01-31 21:21:22 +0100 <dminuoso> What do you mean by "scopes"?
2025-01-31 21:21:33 +0100 <euouae> I guess there's no such thing
2025-01-31 21:21:39 +0100 <euouae> Well I imagine the situation:
2025-01-31 21:21:48 +0100ubert(~Thunderbi@p200300ecdf4e6362e6fd4bc8009ee988.dip0.t-ipconnect.de) (Remote host closed the connection)
2025-01-31 21:21:55 +0100 <euouae> `f x` has to be evaluated. In different parts of the program there's `f x`, is that all shared?
2025-01-31 21:21:56 +0100 <dminuoso> Say you have `let x = <expensive> in x + x`, then both references of `x` will point at the same location in memory.
2025-01-31 21:22:05 +0100 <dminuoso> euouae: Maybe.
2025-01-31 21:22:07 +0100 <dminuoso> It depends.
2025-01-31 21:22:21 +0100 <euouae> I think for one thing, if these are different threads, I'm willing to bet it's not
2025-01-31 21:22:37 +0100 <dminuoso> euouae: In GHC the simplifier has both reasons to *try* to do it, and reasons to try and not share.
2025-01-31 21:22:37 +0100 <euouae> but for a single process, I'm also sure that GHC must have limited memory of how much should be shared?
2025-01-31 21:23:06 +0100 <euouae> So, sharing seems to me to be strictly an optimization right? Or does it affect side-effects?
2025-01-31 21:23:16 +0100 <dminuoso> Now thats an excellent question.
2025-01-31 21:23:22 +0100 <dminuoso> In principle its optimization only.
2025-01-31 21:23:45 +0100 <dminuoso> However, we have dirty little primitives that we can use to embed side effects into evaluation with, which makes the difference observable
2025-01-31 21:24:04 +0100ubert(~Thunderbi@p200300ecdf4e6362e6fd4bc8009ee988.dip0.t-ipconnect.de) ubert
2025-01-31 21:24:16 +0100 <dminuoso> But you can safely forget about those primitives after our discussion.
2025-01-31 21:24:54 +0100 <dminuoso> Or actually, let me introduce you to one that is helpful to beginners:
2025-01-31 21:24:56 +0100 <euouae> hm...
2025-01-31 21:25:03 +0100 <dminuoso> Debug.Trace.trace
2025-01-31 21:25:19 +0100 <dminuoso> That primitive attaches a string to some arbitrary thing, and when that thing gets evaluated the string gets printed.
2025-01-31 21:25:29 +0100 <dminuoso> Which is highly useful for debugging pure code.
2025-01-31 21:25:46 +0100 <dminuoso> However, because it gets triggered upon evaluation, any of the following scenarios can happen:
2025-01-31 21:26:14 +0100 <dminuoso> It never gets printed, it gets printed once, or many times.
2025-01-31 21:26:29 +0100 <dminuoso> Which for debugging is usually not an issue, of course.
2025-01-31 21:26:45 +0100 <dminuoso> % import Debug.Trace
2025-01-31 21:26:45 +0100 <yahb2> <no output>
2025-01-31 21:27:39 +0100 <euouae> so Debug.Trace.Trace can show you the effect of sharing
2025-01-31 21:27:41 +0100 <dminuoso> % let x = trace "demanded" (2.5 ^ 10) in (x, x)
2025-01-31 21:27:41 +0100 <yahb2> demanded ; demanded ; (9536.7431640625,9536.7431640625)
2025-01-31 21:27:48 +0100 <dminuoso> Here you can see sharing did not kick in
2025-01-31 21:28:09 +0100 <euouae> How did you know that the expr wouldn't be shared
2025-01-31 21:28:31 +0100alfiee(~alfiee@user/alfiee) alfiee
2025-01-31 21:28:38 +0100 <dminuoso> I tried it in a DM beforehand.
2025-01-31 21:28:48 +0100 <mauke> % let x = trace "demanded" (2.5 ^ 10 :: Double) in (x, x)
2025-01-31 21:28:48 +0100 <yahb2> demanded ; (9536.7431640625,9536.7431640625)
2025-01-31 21:28:53 +0100 <mauke> hah
2025-01-31 21:28:57 +0100 <euouae> but what made you think that arithmetic wouldn't work?
2025-01-31 21:29:13 +0100tomboy64(~tomboy64@user/tomboy64) (Read error: Connection reset by peer)
2025-01-31 21:29:20 +0100 <dminuoso> euouae: Well to be fair I have some additional knowledge, but I dont want to ovecomplicate the discussion.
2025-01-31 21:29:30 +0100tomboy64(~tomboy64@user/tomboy64) tomboy64
2025-01-31 21:29:37 +0100 <euouae> So it's pretty deep / internal
2025-01-31 21:29:49 +0100 <mauke> <euouae> So, sharing seems to me to be strictly an optimization right? <- no, unwanted sharing can increase memory use a lot
2025-01-31 21:30:01 +0100 <euouae> Well what if the expression has side effects? Does sharing get turned off?
2025-01-31 21:30:04 +0100 <dminuoso> Sometimes sharing is great, sometimes you want everything inlined.
2025-01-31 21:30:10 +0100 <euouae> or is it still anyone's game? maybe shared maybe not?
2025-01-31 21:30:12 +0100 <dminuoso> euouae: expressions dont have side effects.
2025-01-31 21:30:25 +0100 <mauke> dminuoso: except when they do, as you just demonstrated :-)
2025-01-31 21:30:25 +0100 <euouae> ah interesting. let me digest that
2025-01-31 21:31:06 +0100 <euouae> well, putStrLn "foo" has a side effect
2025-01-31 21:31:14 +0100 <dminuoso> euouae: No it does not.
2025-01-31 21:31:18 +0100 <mauke> as far as I know there is no specific protection here. ghc shares things or not; if you (unsafely) embed side effects in your expressions, you have to be ready to handle either case
2025-01-31 21:31:21 +0100 <dminuoso> euouae: We have a primitive to force evaluation to prove this:
2025-01-31 21:31:39 +0100 <dminuoso> % putStrLn () `seq` ()
2025-01-31 21:31:39 +0100 <yahb2> <interactive>:109:10: error: [GHC-83865] ; • Couldn't match type ‘()’ with ‘[Char]’ ; Expected: String ; Actual: () ; • In the first argument of ‘putStrLn’, namely ‘()’ ; ...
2025-01-31 21:31:50 +0100 <dminuoso> % putStrLn "hello world" `seq` ()
2025-01-31 21:31:50 +0100 <yahb2> ()
2025-01-31 21:32:01 +0100 <dminuoso> euouae: Here seq forces its first argument and returns the second.
2025-01-31 21:32:07 +0100 <dminuoso> See how the evaluation did not cause any side effect?
2025-01-31 21:32:21 +0100 <mauke> putStrLn is basically just a constructor. it builds an IO () value
2025-01-31 21:32:29 +0100 <dminuoso> A good mind model is that IO is just a list of assembly instructions, and calculating the list of assembly instrutions is pure/side-effect free.
2025-01-31 21:32:50 +0100 <dminuoso> i.e. calculating a list of assembly instructions is different from executing them.
2025-01-31 21:32:53 +0100alfiee(~alfiee@user/alfiee) (Ping timeout: 248 seconds)
2025-01-31 21:32:55 +0100 <mauke> that's a good model if you already know asm; not so much otherwise :-)
2025-01-31 21:33:00 +0100 <euouae> Okay right (yeah I know asm)
2025-01-31 21:33:10 +0100 <euouae> I see then, nothing special about IO
2025-01-31 21:33:23 +0100 <dminuoso> euouae: its `trace` that is special. :-)
2025-01-31 21:33:24 +0100 <euouae> Well, what is the unwanted sharing that increases memory?
2025-01-31 21:33:56 +0100 <dminuoso> euouae: It can keep stuff alive in memory longer than you want to.
2025-01-31 21:34:08 +0100 <euouae> Ah yeah that makes sense
2025-01-31 21:34:20 +0100 <dminuoso> But not sharing can also waste memory in potentially having to keep it in memory multiple times..
2025-01-31 21:34:36 +0100 <mauke> > let { x = [0 ..]; y = [0 ..] } in (x !! 10000) + (y !! 9999)
2025-01-31 21:34:38 +0100 <lambdabot> 19999
2025-01-31 21:34:38 +0100 <euouae> So when "executing" haskell code, theoretically you can imagine that all the grammatical expansions happen at runtime. Obviously "compiled" haskell code can do some of the work before hand
2025-01-31 21:34:57 +0100 <dminuoso> euouae: You mean *evaluating* right?
2025-01-31 21:34:58 +0100 <euouae> But feigning ignorance on compilation, it's fine to think of it as all interpreted at runtime right?
2025-01-31 21:35:14 +0100 <dminuoso> euouae: But yes, you can imagine that substitution happens at runtime.
2025-01-31 21:35:14 +0100 <mauke> in my example, if nothing is shared, the code can run in O(1) memory
2025-01-31 21:35:16 +0100 <euouae> Yeah right, evaluating
2025-01-31 21:35:25 +0100 <dminuoso> Yes, you can imagine this happens at runtime.
2025-01-31 21:35:33 +0100 <euouae> dminuoso: I'm very prone to using the wrong terms all the time
2025-01-31 21:35:35 +0100 <dminuoso> Of course *executing* IO also happens at runtime and is done by main.
2025-01-31 21:35:51 +0100 <dminuoso> That is, main is the only thing (aside from some dark primitives) that can execute IO.
2025-01-31 21:36:02 +0100 <mauke> I don't think that's the right way to think about it
2025-01-31 21:36:05 +0100 <mauke> main is just a constant
2025-01-31 21:36:20 +0100 <mauke> the runtime system grabs the value of main and runs the instructions you built
2025-01-31 21:36:32 +0100 <euouae> Well GHC bootstraps some code before main to do the execution
2025-01-31 21:36:36 +0100 <euouae> very similar to C etc
2025-01-31 21:36:41 +0100 <mauke> yes
2025-01-31 21:36:43 +0100 <dminuoso> euouae: Right.
2025-01-31 21:36:58 +0100 <euouae> so what about threads? is sharing happening across threads?
2025-01-31 21:37:11 +0100 <dminuoso> Oh you're really diving deep now.
2025-01-31 21:37:15 +0100 <mauke> my point is that just as main() is a regular C function (has an address, can be called from inside the program, etc), so Haskell main is a regular IO () value and can be used as such
2025-01-31 21:37:34 +0100 <mauke> euouae: yes
2025-01-31 21:37:40 +0100sprotte24(~sprotte24@p200300d16f06b9001d5c2b08794be0ce.dip0.t-ipconnect.de)
2025-01-31 21:37:49 +0100 <euouae> Oh it does? That can be bad
2025-01-31 21:38:02 +0100 <euouae> I can see why memory can blow up then
2025-01-31 21:38:02 +0100 <dminuoso> No, its all build to handle that.
2025-01-31 21:38:12 +0100 <mauke> on a related topic, have you ever seen the <<loop>> exception?
2025-01-31 21:38:18 +0100 <euouae> No
2025-01-31 21:38:36 +0100 <mauke> > let x = head [x] in x
2025-01-31 21:38:37 +0100 <dminuoso> euouae: First off, when switchinig between threads, entered thunks are blackholed.
2025-01-31 21:38:38 +0100 <lambdabot> *Exception: <<loop>>
2025-01-31 21:38:58 +0100 <dminuoso> euouae: That is, there is automatic protection that no two threads attempt to evaluate the same expression concurrently.
2025-01-31 21:39:25 +0100 <dminuoso> And that all alone pretty much stops memory issues.
2025-01-31 21:39:37 +0100 <mauke> I may be wrong on my terminology, but I think blackholing only happens in single-threaded mode
2025-01-31 21:40:03 +0100 <dminuoso> See https://simonmar.github.io/bib/papers/multiproc.pdf
2025-01-31 21:41:06 +0100 <mauke> huh, interesting
2025-01-31 21:41:55 +0100 <mauke> anyway, the <<loop>> exception happens when evaluation of a thunk tries to re-enter the same thunk (i.e. you have a value that depends on itself)
2025-01-31 21:41:58 +0100euouaefuriously types some notes of the previous discussion, needs more time to read the latest stuff being said
2025-01-31 21:42:30 +0100 <mauke> this is implemented by temporarily switching the code pointer of a thunk to a subroutine that throws an exception
2025-01-31 21:42:48 +0100 <mauke> at least in single-threaded mode
2025-01-31 21:43:33 +0100 <mauke> in a multi-threaded environment, the first thread to reach a given thunk instead switches out the code pointer to an "enter waiting queue" subroutine
2025-01-31 21:44:07 +0100 <mauke> so if another thread tries to evaluate the same thunk later, it will simply wait until the first thread is done computing a value
2025-01-31 21:44:08 +0100alexherbo2(~alexherbo@2a02-8440-3503-94e0-1866-04f2-f81a-c1ec.rev.sfr.net) (Remote host closed the connection)
2025-01-31 21:44:25 +0100 <dminuoso> mauke: Okay, so there's two behaviors to blackhole.
2025-01-31 21:44:33 +0100 <dminuoso> mauke: If the same thread enters a blackhole, that blackhole acts as loop detection.,
2025-01-31 21:44:48 +0100 <dminuoso> If another thread enters a blackhole, it gets put on a list to be woken up later.
2025-01-31 21:45:04 +0100 <dminuoso> So it gets woken up whenever the thunk finished.
2025-01-31 21:45:18 +0100 <mauke> did they change that? I have a vague memory that <<loop>> detection didn't work in multi-thread mode
2025-01-31 21:45:23 +0100 <dminuoso> The <<loop>> is just some opportunistic debugging helper, its not the core feature.
2025-01-31 21:45:44 +0100dsrt^(~dsrt@108.192.66.114) (Ping timeout: 252 seconds)
2025-01-31 21:45:54 +0100 <dminuoso> (And it does not work reliably either for a bunch of reasons)
2025-01-31 21:46:00 +0100 <mauke> i.e. in multi-thread mode a thread could re-enter the thunk and end up waiting for itself (deadlock)
2025-01-31 21:46:05 +0100 <dminuoso> So consider it a bonus *if* it triggers.
2025-01-31 21:48:08 +0100 <dminuoso> mauke: Im not sure how the threaded RTS changes, but blackholing should be needed for single threaded RTS too.
2025-01-31 21:48:24 +0100 <dminuoso> Note that "threaded RTS" talks about OS threads
2025-01-31 21:48:34 +0100 <dminuoso> While the other use of threads if about haskell threads.
2025-01-31 21:49:09 +0100 <mauke> ah, right
2025-01-31 21:49:12 +0100 <dminuoso> Even in single threaded RTS you will have concurrency.
2025-01-31 21:49:44 +0100 <euouae> mauke, is <<loop>> possible because of sharing?
2025-01-31 21:49:53 +0100 <euouae> sorry I'm reading from the top so I'm trying to catch up on what was said
2025-01-31 21:50:25 +0100 <dminuoso> euouae: So roughly, if you have `let x = <expensive> in ..` then we can think of x being represented in memory as some memory region with a bunch of code
2025-01-31 21:50:41 +0100 <dminuoso> euouae: and you demand that value by just jmp'ing into that memory region.
2025-01-31 21:51:15 +0100 <euouae> interestingly `let x = head [x] in x` just hangs in ghci
2025-01-31 21:51:39 +0100 <dminuoso> Now that entry code both checks for a particular mark BLACKHOLE to be set, if its set, you get a <<loop>> assuming this happened from within the same haskell thread.
2025-01-31 21:51:48 +0100 <dminuoso> If not, it will set that mark.
2025-01-31 21:51:58 +0100 <euouae> oh mauke's example relates to black holes? I'll read the whole convo then
2025-01-31 21:52:24 +0100 <dminuoso> You can think of it as some kind of mutual exclusion lock, but with special logic to detect if the entry code recursed into itself.
2025-01-31 21:52:42 +0100 <dminuoso> mauke: Yes. Its really just a kind of mutual exclusion lock for thunks.
2025-01-31 21:53:08 +0100 <dminuoso> It was recognized we could use the same machinery to detect some forms of infinite loops
2025-01-31 21:53:39 +0100 <ash3en> using jack midi with haskell: do i have to manage memory or something?
2025-01-31 21:53:53 +0100 <ash3en> i mean the haskell library: https://hackage.haskell.org/package/jack-0.7.2.2/docs/Sound-JACK-MIDI.html
2025-01-31 21:56:05 +0100 <dminuoso> euouae: https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/rts/storage/heap-objects
2025-01-31 21:56:11 +0100 <dminuoso> Is a good website to remember.
2025-01-31 21:56:29 +0100 <dminuoso> euouae: Start with the `Heap Objects` section
2025-01-31 21:57:29 +0100sarna(~sarna@d224-221.icpnet.pl) (Ping timeout: 260 seconds)
2025-01-31 21:57:48 +0100 <dminuoso> euouae: Note, that every object has a pointer to an info table, and that info table contains entry code. Evaluation is driven by just jumping into that entry code
2025-01-31 21:58:16 +0100sarna(~sarna@d224-221.icpnet.pl) sarna
2025-01-31 21:58:17 +0100 <dminuoso> See https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/rts/storage/heap-objects#black-holes for some details on blackhole
2025-01-31 21:59:14 +0100 <euouae> yeah I was thinking that <<loop>> detection seems roughly like the halting prolbem
2025-01-31 21:59:23 +0100 <euouae> so maybe it's not reliable, just a heuristic?
2025-01-31 22:00:00 +0100 <dminuoso> euouae: Like I said: It can only detect a particular kind of infinite loop.
2025-01-31 22:00:08 +0100 <euouae> right
2025-01-31 22:00:09 +0100 <dminuoso> Its not even a heuristic.
2025-01-31 22:00:43 +0100 <euouae> well eah, that's good, heuristics can misfire
2025-01-31 22:01:09 +0100 <dminuoso> If it triggers, there's definitely an infinite loop and you can celebrate. :)
2025-01-31 22:01:16 +0100 <mauke> if you encounter the buddha on the road, kill him
2025-01-31 22:01:18 +0100 <dminuoso> But dont ever rely on it firing.
2025-01-31 22:01:29 +0100kimiamania8(~65804703@user/kimiamania) (Quit: PegeLinux)
2025-01-31 22:01:35 +0100 <mauke> only in this case it's more like "if you encounter yourself on the road, kill the current thread"
2025-01-31 22:01:53 +0100kimiamania8(~65804703@user/kimiamania) kimiamania
2025-01-31 22:02:02 +0100 <dminuoso> euouae: Like I said, the machinery was not build for loop detection but for preventing concurrent evaluation of the same thunk between two haskell threads.
2025-01-31 22:02:30 +0100CoolMa7(~CoolMa7@ip5f5b8957.dynamic.kabel-deutschland.de) CoolMa7
2025-01-31 22:03:50 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 244 seconds)
2025-01-31 22:04:17 +0100 <euouae> yup yup
2025-01-31 22:04:21 +0100ubert(~Thunderbi@p200300ecdf4e6362e6fd4bc8009ee988.dip0.t-ipconnect.de) (Quit: ubert)
2025-01-31 22:04:25 +0100 <monochrom> It helps avoid multiple threads doing redundant work. It is not even a 100% perfect lock, for no one needs one, in case two threads do happen to slip through and perform redundant work, it is just slower but still correct, this is an immutable language, evaluating x+y a million times does not change the answer.
2025-01-31 22:04:29 +0100 <euouae> I've written & digested all that was said today, and thanks for more homework
2025-01-31 22:04:38 +0100ubert(~Thunderbi@p200300ecdf4e63626546ad8bed5a8da9.dip0.t-ipconnect.de) ubert
2025-01-31 22:04:54 +0100 <euouae> I am curious, you said single RTS still has haskell threads, were you referring to some concurrent library or what happens behind the scenes by ghc itself?
2025-01-31 22:05:52 +0100 <mauke> the RTS does m:n threading anyway (running m haskell threads on n native threads), so n = 1 is supported as well
2025-01-31 22:05:59 +0100 <euouae> what does RTS stand for?
2025-01-31 22:06:03 +0100 <mauke> runtime system
2025-01-31 22:06:03 +0100 <monochrom> The "threaded RTS" uses OS threads (so hopefully spreading out on more cores if you have them). The "unthreaded RTS" makes its own green threads, if you have heard of that word.
2025-01-31 22:06:11 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-01-31 22:06:27 +0100 <euouae> yup I've heard of green threads, I'm just curious if Haskell has them behind the scenes or if it was in regards to the programmer's usage
2025-01-31 22:06:31 +0100 <mauke> also a good term: event loop
2025-01-31 22:06:54 +0100 <dminuoso> By the way, in reality whether or not a thunk gets marked as blackhole on entry depends on whether you opted into eager blackholing or use the default lazy blackholing
2025-01-31 22:06:58 +0100 <monochrom> The good news is "why not both".
2025-01-31 22:07:01 +0100 <dminuoso> Details are described in https://gitlab.haskell.org/ghc/ghc/-/blob/wip/T17910/rts/Updates.h
2025-01-31 22:07:29 +0100 <monochrom> and yeah the threaded RTS simply distributes 10000 green threads over 4 OS threads.
2025-01-31 22:07:46 +0100 <euouae> what does RTS stand for?
2025-01-31 22:07:49 +0100 <monochrom> or s/4/whatever you say in -N/
2025-01-31 22:07:51 +0100 <dminuoso> Runtime System
2025-01-31 22:07:59 +0100 <euouae> Ok so it's the thing that runs the green threads or OS threads etc
2025-01-31 22:08:11 +0100 <dminuoso> So one of the things that Haskell is rather unique in, is the way IO is handled.
2025-01-31 22:08:33 +0100 <dminuoso> Most IO appears to be synchronous, but is done completely asynchronously with the RTS knowing about it.
2025-01-31 22:08:49 +0100 <dminuoso> As a consequence, threads get scheduled accordingly whether IO calls are ready/finished
2025-01-31 22:09:19 +0100 <dminuoso> So you kind of get the convenience of synchronous code, without having to coordinate/yield all over the place