Newest at the top
| 2026-04-06 14:08:09 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 248 seconds) |
| 2026-04-06 14:03:08 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn |
| 2026-04-06 13:56:03 +0000 | <TMA> | my understanding of I/O in Haskell stopped with threading RealWorld through everything |
| 2026-04-06 13:55:59 +0000 | bitdex | (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "") |
| 2026-04-06 13:52:30 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 255 seconds) |
| 2026-04-06 13:48:49 +0000 | tromp | (~textual@2001:1c00:340e:2700:8cf8:7bb7:a0e:7cfa) |
| 2026-04-06 13:47:21 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn |
| 2026-04-06 13:42:09 +0000 | synchromesh | (~john@2406:5a00:2412:2c00:75ab:7cb0:db12:1e18) synchromesh |
| 2026-04-06 13:41:32 +0000 | <lambdabot> | newtype Cont r a = Cont { runCont :: (a -> r) -> r } |
| 2026-04-06 13:41:32 +0000 | <ski> | @src Cont |
| 2026-04-06 13:41:13 +0000 | <lambdabot> | (Char -> Dialogue) -> Dialogue |
| 2026-04-06 13:41:13 +0000 | <ski> | @unmtl Cont Dialogue Char |
| 2026-04-06 13:41:03 +0000 | <ski> | (btw, this `(Char -> Dialogue) -> Dialogue' can be expressed as a "continuation monad", `Cont Dialogue Char', and similarly `Cont Dialogue ()' for the output case) |
| 2026-04-06 13:40:50 +0000 | synchromesh | (~john@2406:5a00:2412:2c00:75ab:7cb0:db12:1e18) (Read error: Connection reset by peer) |
| 2026-04-06 13:40:35 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) (Ping timeout: 245 seconds) |
| 2026-04-06 13:40:04 +0000 | <ski> | in this case, there'd be a thin run-time driver, which inspects the requests from the dialogue, performs it, and then generates the corresponding response for the dialogue to receive |
| 2026-04-06 13:37:16 +0000 | <ski> | where you pass a "continuation" dialogue for what to do (which will generate the remaining requests and process the corresponding responses), after the character you've outputted, or inputted |
| 2026-04-06 13:35:45 +0000 | <ski> | hGetChar h c_cont resps0 = HGetChar h : case resps0 of HCharGot c:resps -> c_cont c resps |
| 2026-04-06 13:35:12 +0000 | <ski> | hGetChar :: Handle -> (Char -> Dialogue) -> Dialogue |
| 2026-04-06 13:35:00 +0000 | <ski> | and |
| 2026-04-06 13:34:57 +0000 | <ski> | hPutChar h c cont resps0 = HPutChar h c : case resps0 of HCharPut:resps -> cont resps |
| 2026-04-06 13:33:53 +0000 | merijn | (~merijn@host-cl.cgnat-g.v4.dfn.nl) merijn |
| 2026-04-06 13:33:46 +0000 | <ski> | hPutChar :: Handle -> Char -> Dialogue -> Dialogue |
| 2026-04-06 13:33:28 +0000 | <ski> | and then you can define helper functions like |
| 2026-04-06 13:33:17 +0000 | terrorjack | (~terrorjac@static.27.101.55.162.clients.your-server.de) terrorjack |
| 2026-04-06 13:33:03 +0000 | Pozyomka | (~pyon@user/pyon) (Quit: bbml) |
| 2026-04-06 13:32:58 +0000 | <ski> | data Response = FileOpened Handle | HCharGot Char | HCharPut | ... |
| 2026-04-06 13:32:22 +0000 | <ski> | data Request = OpenFile FilePath IOMode | HGetChar Handle | HPutChar Handle Char | ... |
| 2026-04-06 13:32:07 +0000 | somemathguy | (~somemathg@user/somemathguy) somemathguy |
| 2026-04-06 13:31:18 +0000 | <ski> | something like |
| 2026-04-06 13:31:09 +0000 | <ski> | iowy, you write a function which returns a lazy list of I/O requests, and then (after generating the current request), you look at the current response |
| 2026-04-06 13:30:13 +0000 | <ski> | type Dialogue = [Responses] -> [Requests] |
| 2026-04-06 13:30:00 +0000 | <ski> | where |
| 2026-04-06 13:29:59 +0000 | <ski> | main :: Dialogue |
| 2026-04-06 13:29:55 +0000 | <ski> | btw, before monadic I/O was introduces in Haskell, there was a "dialogue"-style I/O, where you defined |
| 2026-04-06 13:29:10 +0000 | sonny | (~sonny@bras-base-london140cw-grc-17-142-113-177-150.dsl.bell.ca) (Quit: Client closed) |
| 2026-04-06 13:29:08 +0000 | terrorjack | (~terrorjac@2a01:4f8:271:2d98::2) (Quit: The Lounge - https://thelounge.chat) |
| 2026-04-06 13:28:41 +0000 | <ski> | (er, s/hGetChar/HGetChar/) |
| 2026-04-06 13:28:30 +0000 | <ski> | you could write an interpreter, `runMyIO :: MyIO a -> IO a', for this |
| 2026-04-06 13:28:07 +0000 | <ski> | and so on |
| 2026-04-06 13:28:05 +0000 | <ski> | ... |
| 2026-04-06 13:28:03 +0000 | <ski> | HPutChar :: Handle -> Char -> MyIO () |
| 2026-04-06 13:27:51 +0000 | <ski> | hGetChar :: Handle -> MyIO Char |
| 2026-04-06 13:27:38 +0000 | <ski> | OpenFile :: FilePath -> IOMode -> MyIO Handle |
| 2026-04-06 13:27:17 +0000 | <ski> | Bind :: MyIO a -> (a -> MyIO b) -> MyIO b |
| 2026-04-06 13:27:04 +0000 | <ski> | Return :: a -> MyIO a |
| 2026-04-06 13:26:58 +0000 | <ski> | where |
| 2026-04-06 13:26:56 +0000 | <ski> | data MyIO :: * -> * |
| 2026-04-06 13:26:31 +0000 | <ski> | if you want to, you could imagine a data type something like |
| 2026-04-06 13:25:52 +0000 | <ski> | (for efficiency, it does get compiled, by GHC, to code that directly performs the indicated actions, rather than interpreting data structures) |