Logs: liberachat/#haskell
| 2025-11-28 18:55:15 | <EvanR> | your code doesn't have to deal with that |
| 2025-11-28 18:55:29 | <EvanR> | just like the repl automatically shows you the answer to an evaluation, you don't have to "print" it |
| 2025-11-28 18:55:40 | <geekosaur> | kinda like how IO can be done in a pure language by, in effect, purely constructing an impure program for the RTS to run impurely |
| 2025-11-28 18:55:56 | <milan> | But this "painting" showing cannot be possibly pure ever right? |
| 2025-11-28 18:56:13 | <geekosaur> | it's not done by your code, it's done by the browser |
| 2025-11-28 18:56:16 | <EvanR> | the word "pure" keeps growing more legs, people applying it into any situation ever |
| 2025-11-28 18:56:22 | <geekosaur> | you purely construct code the browser runs impurely |
| 2025-11-28 18:56:29 | <milan> | Eh |
| 2025-11-28 18:56:33 | <EvanR> | a pure function is a function |
| 2025-11-28 18:56:43 | <milan> | That has no side effects right? |
| 2025-11-28 18:56:45 | <EvanR> | a client side framework isn't a function |
| 2025-11-28 18:56:57 | <EvanR> | so it's not necessarily meaning for you to call it pure or not |
| 2025-11-28 18:57:00 | <EvanR> | similar to "pure data" |
| 2025-11-28 18:57:10 | <EvanR> | you'd have to specify what that even means, since data isn't a function |
| 2025-11-28 18:57:24 | <EvanR> | *meaningful |
| 2025-11-28 18:58:26 | <EvanR> | think of a browser window as the final UI screen observable to the user, it's not a function, it's a thing you send content to be displayed |
| 2025-11-28 18:58:32 | <EvanR> | like a terminal |
| 2025-11-28 18:59:01 | <milan> | Agree |
| 2025-11-28 18:59:33 | <EvanR> | if that's all it is then it's possible to get a lot done using only pure functions |
| 2025-11-28 18:59:39 | <EvanR> | and data |
| 2025-11-28 18:59:52 | <EvanR> | something behind the scenes just hooks it up |
| 2025-11-28 19:02:41 | <milan> | Yes, but... I understand why reading from (external object) is not pure.. You can always read something else so now your function can return different things. But why writing to external object is also considered impure? Wheter it succeds or not can't affect my pure program right? |
| 2025-11-28 19:03:08 | × | infinity0 quits (~infinity0@pwned.gg) (Quit: WeeChat 4.6.3) |
| 2025-11-28 19:03:11 | <milan> | So simply printing to console should not be considered "impure" and thus in IO monad? |
| 2025-11-28 19:03:24 | <EvanR> | that is why you can type purely function programs in the repl and see the result |
| 2025-11-28 19:03:41 | <EvanR> | easily |
| 2025-11-28 19:03:52 | <EvanR> | the tower of machinery to get that on the screen has no effect on the program |
| 2025-11-28 19:04:12 | <EvanR> | which is good because there's a lot |
| 2025-11-28 19:04:43 | <milan> | Yet print :: Show a => a -> IO() ? |
| 2025-11-28 19:04:51 | <milan> | EvanR: Agree |
| 2025-11-28 19:05:05 | <EvanR> | print has that type, why is that "yet" |
| 2025-11-28 19:05:19 | <EvanR> | (note you don't have to type print to see the result in the repl) |
| 2025-11-28 19:05:51 | <EvanR> | also have to decorum and put a space between IO and () |
| 2025-11-28 19:06:03 | <EvanR> | have some* xD |
| 2025-11-28 19:06:23 | <milan> | :D My apologies |
| 2025-11-28 19:06:49 | × | ljdarj quits (~Thunderbi@user/ljdarj) (Ping timeout: 246 seconds) |
| 2025-11-28 19:06:53 | → | ljdarj1 joins (~Thunderbi@user/ljdarj) |
| 2025-11-28 19:06:57 | → | tzh joins (~tzh@c-76-115-131-146.hsd1.or.comcast.net) |
| 2025-11-28 19:07:13 | <milan> | Why print does not have type a -> Int? And always produce number 1? Why is it IO? |
| 2025-11-28 19:07:36 | <EvanR> | you're asking why the print function doesn't return a number |
| 2025-11-28 19:07:48 | <EvanR> | i.e. print 3 yields the number 3 or something? |
| 2025-11-28 19:07:54 | <milan> | No I am asking why it returns Monad if it does not have to |
| 2025-11-28 19:08:10 | <milan> | No it always yields 1 |
| 2025-11-28 19:08:27 | <EvanR> | what behavior do you want the function to have again |
| 2025-11-28 19:08:40 | <EvanR> | while being a pure function |
| 2025-11-28 19:08:48 | <EvanR> | always returning 1 would be const 1 |
| 2025-11-28 19:09:07 | <EvanR> | :t const 1 |
| 2025-11-28 19:09:08 | <lambdabot> | Num a => b -> a |
| 2025-11-28 19:09:12 | ljdarj1 | is now known as ljdarj |
| 2025-11-28 19:10:03 | <EvanR> | note it wouldn't be a very good print function, for one thing you don't know the input has Show support |
| 2025-11-28 19:10:55 | <milan> | What about myPrint :: Show a => a -> Int ? |
| 2025-11-28 19:11:09 | <mniip> | referential transparency says that `(print 3, print 3)` and `let x = print 3 in (x, x)` must do the same thing, but you'd expect the first one to output twice and the second one only once |
| 2025-11-28 19:11:27 | <milan> | mniip: hmm... |
| 2025-11-28 19:11:42 | <EvanR> | if myPrint is a pure function, then it means you can't observe any side effects |
| 2025-11-28 19:11:47 | <mniip> | this is why pure functions cannot perform side effects such as output something to the console |
| 2025-11-28 19:12:11 | <EvanR> | so it's not going to be great at printing anything |
| 2025-11-28 19:12:25 | <milan> | Had we dropped our expectation on how and if something must appear in console? |
| 2025-11-28 19:12:37 | <milan> | Well |
| 2025-11-28 19:12:44 | <milan> | Then all programs would be unusable |
| 2025-11-28 19:12:50 | <EvanR> | not necessarily |
| 2025-11-28 19:13:05 | <mniip> | if you're looking for something to use while debugging pure code, there is such a tool |
| 2025-11-28 19:13:07 | <EvanR> | your calculator is useful despite not having any I/O commands |
| 2025-11-28 19:13:21 | <milan> | It has it has display |
| 2025-11-28 19:13:25 | <milan> | same as console |
| 2025-11-28 19:13:39 | <EvanR> | I figured you were talking about the programming language though, not the hardware |
| 2025-11-28 19:13:40 | <milan> | or file that we can write to.. or socket we can write to.. |
| 2025-11-28 19:13:41 | → | tromp joins (~textual@2001:1c00:3487:1b00:9176:7929:ae5a:d4f6) |
| 2025-11-28 19:14:15 | <EvanR> | haskell is a purely functional programming language, not purely functional hardware |
| 2025-11-28 19:14:34 | <milan> | Some external object that might or might not correctly change state because we asked it to... it is same for display in calculator, and same for file in disk. |
| 2025-11-28 19:14:47 | <EvanR> | that's just the supporting infrastructure for the runtime |
| 2025-11-28 19:15:10 | <EvanR> | as the program runs, the I/O commands it computes are executed |
| 2025-11-28 19:15:18 | <EvanR> | main :: IO () |
| 2025-11-28 19:15:43 | <EvanR> | e.g. main = print 3 >> print 3 :: IO () |
| 2025-11-28 19:15:50 | <EvanR> | would print twice |
| 2025-11-28 19:15:53 | <milan> | Yep |
| 2025-11-28 19:16:00 | <EvanR> | but the program itself just computes data |
| 2025-11-28 19:16:20 | <EvanR> | you could store the IO () in a data structure or mutable variable for later |
| 2025-11-28 19:16:28 | <EvanR> | or pass it as an argument |
| 2025-11-28 19:16:41 | <EvanR> | :t bracket |
| 2025-11-28 19:16:42 | <lambdabot> | IO a -> (a -> IO b) -> (a -> IO c) -> IO c |
| 2025-11-28 19:16:53 | × | ChaiTRex quits (~ChaiTRex@user/chaitrex) (Remote host closed the connection) |
| 2025-11-28 19:17:00 | <EvanR> | in this way you can build up a big IO from smaller ones |
| 2025-11-28 19:17:04 | <EvanR> | algebraically |
| 2025-11-28 19:17:22 | → | ChaiTRex joins (~ChaiTRex@user/chaitrex) |
| 2025-11-28 19:17:32 | <milan> | I agree |
| 2025-11-28 19:18:04 | <EvanR> | just evaluating print 3 by itself wouldn't necessarily do the IO i.e. in (print 3, print 3), so it's a big distinction to make |
| 2025-11-28 19:18:22 | × | acidjnk quits (~acidjnk@p200300d6e7171911dda60d32ed7e3ae9.dip0.t-ipconnect.de) (Ping timeout: 246 seconds) |
| 2025-11-28 19:18:57 | <milan> | hmm |
| 2025-11-28 19:19:42 | <EvanR> | in most language the evaluation of a function call is intertwined with executing effects, which is why you have to wrap everything with a lambda wrapper to delay the effects |
| 2025-11-28 19:19:59 | <EvanR> | so they don't happen until someone calls the function |
| 2025-11-28 19:20:06 | <EvanR> | in haskell they're two different things entirely |
| 2025-11-28 19:21:23 | <milan> | I get that they are encapsulated in IO... |
| 2025-11-28 19:22:02 | <EvanR> | yeah so, functions are over here and are like this, and I/O commands are over here |
| 2025-11-28 19:22:21 | <EvanR> | orthogonal, but can be combined easily |
| 2025-11-28 19:22:22 | <milan> | And as runtime is evaluating big IO composed of smaler IOs it always executes action there. |
| 2025-11-28 19:22:43 | <mniip> | the bonus is that IO actions are values and you can manipulate them |
| 2025-11-28 19:22:43 | <EvanR> | yes! |
| 2025-11-28 19:23:16 | <mniip> | let x = print 3 in x >> x |
| 2025-11-28 19:23:23 | <mniip> | hell you can put them in a list: sequence_ [x, x, x] |
| 2025-11-28 19:24:35 | <milan> | You can put functions to list too right? |
All times are in UTC.