2025/03/21

Newest at the top

2025-03-21 22:10:30 +0100 <dminuoso> directions!)
2025-03-21 22:10:28 +0100 <dminuoso> Rather than asking "what the difference between pure and impure functions" is, we should rather re-learn the notion of "function" to mean something that is almost, but not quite , entirely unlike its cousin from traditional programming and compare that to "effect". Once you learn them as orthogonal things and advance, you can get into deeper ideas on how to encode one with the other (in both
2025-03-21 22:08:44 +0100euleritian(~euleritia@dynamic-176-006-128-244.176.6.pool.telefonica.de)
2025-03-21 22:07:57 +0100 <ski> there's is a lot of bad "monad tutorials" out there (arguably, most of them are bad, to lesser or greater extents)
2025-03-21 22:07:31 +0100 <ski> yes, there is that too
2025-03-21 22:07:22 +0100 <ski> it can take some times to be able to switch perspectives, to be able to see the relevant distinctions (which you're not used to drawing)
2025-03-21 22:07:18 +0100 <dminuoso> I think plenty of confusion comes from decades of programming having (incorrectly) reused terminology like calling routines functions, and then attaching labels like "pure" and "impure" to differentiate things that should not be compared.
2025-03-21 22:07:15 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 276 seconds)
2025-03-21 22:06:36 +0100 <ski> sim590 : yea, i think the best approach is to ponder it, sleep on it, do examples, think about how you can reason about (including refactoring) programs, come back later to this
2025-03-21 22:05:48 +0100 <ski> so, you can imagine that the run-time system is an imperative program (not written in Haskell), which interprets `IO'-actions similarly to how `runTele' interprets `Tele'-actions, and in addition actually interacts with the OS
2025-03-21 22:05:39 +0100 <sim590> In any case, this whole conversation lasted too long already for me considering I should have been working. So, I'll go back to my employer's task I have to finish. I'll resume investigating purity later. Thanks for the conversation anyway!
2025-03-21 22:04:35 +0100 <ski> you can write a `runTele :: Tele a -> IO a' interpreter, and then calling `runTele' on a `Tele'-action, and then letting the run-time system interpret/execute the resulting `IO'-action, would be equivalent to letting the run-time system interpret/execute the corresponding equivalent `IO'-action directly
2025-03-21 22:03:50 +0100 <EvanR> so it's not lambdas in lambdas there but just data, that happens to use a lambda in a place to get a result
2025-03-21 22:03:27 +0100euleritian(~euleritia@95.90.214.149) (Ping timeout: 244 seconds)
2025-03-21 22:03:12 +0100 <ski> PutC '?' (GetC (\c -> PutC c (PutC '!' (Done ()))))
2025-03-21 22:02:34 +0100kimiamania8(~65804703@user/kimiamania) kimiamania
2025-03-21 22:02:29 +0100 <ski> yes, something like that can be used to try to explain how `IO'-actions can be seen as inert instructions
2025-03-21 22:02:26 +0100 <EvanR> I'm melting
2025-03-21 22:02:17 +0100 <EvanR> no I messed it up
2025-03-21 22:02:09 +0100kimiamania8(~65804703@user/kimiamania) (Quit: PegeLinux)
2025-03-21 22:01:55 +0100 <EvanR> :: Tele ()
2025-03-21 22:01:44 +0100 <EvanR> would be a possible imperative program in haskell, if you defined the right Monad instance
2025-03-21 22:01:42 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) merijn
2025-03-21 22:01:27 +0100 <EvanR> PutC '?' >> GetC >>= \c -> PutC c >> PutC '!' >> Done ()
2025-03-21 22:01:24 +0100 <EvanR> data Tele a = GetC (Char -> Tele a) | PutC Char (Tele a) | Done a
2025-03-21 22:00:08 +0100 <ski> (or the imperative programming, or the imperative behaviour, if you prefer)
2025-03-21 21:59:07 +0100 <ski> but that's not how the imperative instructions here are being expressed
2025-03-21 21:58:59 +0100 <EvanR> imperative programming is a vibe, not a strict concrete thing
2025-03-21 21:58:51 +0100 <ski> that kind of lambda nesting can be used to express a kind of sequencing (from data-dependencies), yes
2025-03-21 21:58:24 +0100 <ski> no
2025-03-21 21:58:18 +0100 <ski> "You could say that lambdas inside lambdas are imperative programming which doesn't make sense." -- yea, i don't think this would make any sense
2025-03-21 21:58:16 +0100 <sim590> You are saying that `(\ x -> (\ y -> x + y) 1) 1` for example is imperative programming?
2025-03-21 21:56:40 +0100 <ski> the value of `main' itself is inert, doesn't "do" anything. only when the run-time system interprets these imperative instructions, does any actual input/output behaviour commence
2025-03-21 21:56:33 +0100jmcantrell(~weechat@user/jmcantrell) jmcantrell
2025-03-21 21:55:59 +0100 <ski> the same holds for `main'. the value of `main' is a "set of instructions describing how to" interact with the OS, in order to effect some observable behaviour on the OS
2025-03-21 21:55:07 +0100 <ski> the contents of the file `/bin/ls' on an Un*x system is not a list of files, but it's a set of instructions describing how to obtain a list of files, if/when executed (interacting with the OS) at some point
2025-03-21 21:53:17 +0100 <ski> does not matter whether you express this with `do' or `>>='
2025-03-21 21:53:00 +0100 <ski> if you write `main = getLine >>= putStrLn', then the value of `main' is an `IO'-action, a recipe, a "sequence of I/O instructions" (although "sequence" is, in general, a bit inaccurate), effectively in an imperative language. this is the imperative programming we're talking about here
2025-03-21 21:52:30 +0100michalz(~michalz@185.246.207.203)
2025-03-21 21:52:00 +0100 <EvanR> cmd1 >>= \result1 -> cmd2 >>= \result2 -> ... return 0
2025-03-21 21:51:31 +0100 <ski> "When you talk about Imperative programming, you talk about `do`, no ?" -- no. talking about reasoning where you have to think about implicit effects of computations, and where ordering (and possible duplication, and omisssion) of computations can have observable behavioural effects on the program
2025-03-21 21:50:59 +0100 <EvanR> concrete syntax is besides the point
2025-03-21 21:50:54 +0100merijn(~merijn@host-vr.cgnat-g.v4.dfn.nl) (Ping timeout: 260 seconds)
2025-03-21 21:50:35 +0100 <EvanR> it's the same thing
2025-03-21 21:50:22 +0100 <EvanR> with semantics, execute the command, pass the result to the next function in the chain to get a new command >>=
2025-03-21 21:50:17 +0100 <ski> "they can easily just do without the `do` operator and just use `>>=`." -- whether they use `do' or not here is irrelevant. doesn't matter
2025-03-21 21:49:54 +0100 <EvanR> chained with >>= sure
2025-03-21 21:49:41 +0100 <sim590> You could say that lambdas inside lambdas are imperative programming which doesn't make sense.
2025-03-21 21:49:22 +0100 <ski> they're reasoning at multiple levels. (a) reasoning on the level of *evaluation* of Haskell expressions (which have no side-effects), and (b) reasoning on the level of *execution* of `IO'-actions (which you can, if you wish, think of as reasoning in a different, side-effectful, language, as sketched above)
2025-03-21 21:49:19 +0100 <EvanR> formatted chain of >>= and lambda for example