Logs on 2021-09-21 (liberachat/#haskell)
| 00:03:33 | <Cale> | There's gi-gtk-hs, which has seemed pretty usable. I've barely been using it though, really, since we've just been drawing most of our UI with cairo :P |
| 00:03:50 | <sclv> | and fltkhs too |
| 00:04:06 | <sclv> | i don't consider the gtk stuff super cross platform based on past experience, but things may be substantially better now |
| 00:04:40 | <sm> | monomer is the latest contender |
| 00:05:02 | <Cale> | Coming at it from another angle, reflex-dom is another option |
| 00:05:25 | <Cajun> | i tried to use monomer a while back and it was a bit broken to say the least |
| 00:05:48 | <sclv> | hrm, hadn't seen it before, might have missed some announcements on it? on the face of it, claims a nice set of features |
| 00:05:52 | <sm> | darn I was just thinking "no-one has panned it yet" |
| 00:06:05 | <sm> | Cajun: do you mean, after you got it installed ? |
| 00:06:17 | <sclv> | 😂 |
| 00:06:23 | × | vysn quits (~vysn@user/vysn) (Remote host closed the connection) |
| 00:06:37 | <Cale> | (We use it to make apps for the Web, iOS and Android mobile devices from the same codebase, which are the three platforms anyone cares about these days.) |
| 00:06:44 | <Cajun> | well that may not entirely be true, it seemed to be tuned for windows (it couldnt find the library on linux) and one of the dev's pushes to a library wasnt fully accepted yet |
| 00:06:46 | <sm> | https://www.reddit.com/r/haskell/comments/p12pjs/ann_monomer_a_gui_library_for_haskell/, sclv |
| 00:07:20 | <Cajun> | i havent checked on it since, but i really do hope it works well |
| 00:07:25 | <sm> | ah, that's small stuff |
| 00:07:50 | <Cajun> | small stuff that made it a pita to deal with, so i just dropped it and promised myself to try it again at a later date |
| 00:08:07 | <sm> | sure, same here (it doesn't build on m1 yet) |
| 00:08:18 | <sm> | s/small/fixable/ |
| 00:09:41 | × | Gurkenglas quits (~Gurkengla@dslb-002-207-014-195.002.207.pools.vodafone-ip.de) (Ping timeout: 264 seconds) |
| 00:09:44 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 00:10:19 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 00:10:57 | → | alx741 joins (~alx741@186.178.109.159) |
| 00:11:02 | <sclv> | reading through monomer's docs i'm reminded again that the "elm architecture" seems to be just like a rebranded mvc |
| 00:11:31 | <sclv> | which i didn't mind when it was in elm, but now seeing it as a term of the art in other contexts is frying my head a bit |
| 00:11:58 | → | Guest57 joins (~Guest57@134.3.172.96) |
| 00:12:27 | → | hexfive joins (~eric@50.35.83.177) |
| 00:12:41 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 00:13:20 | × | jespada quits (~jespada@2803:9800:9842:7a62:edd5:5e74:3ec2:1b19) (Quit: My MacBook has gone to sleep. ZZZzzz…) |
| 00:17:58 | × | Guest57 quits (~Guest57@134.3.172.96) (Quit: Client closed) |
| 00:20:04 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 00:20:40 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 00:22:36 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 00:22:49 | × | hexfive quits (~eric@50.35.83.177) (Quit: WeeChat 3.0.1) |
| 00:25:04 | × | Igloo quits (~ian@matrix.chaos.earth.li) (Ping timeout: 252 seconds) |
| 00:26:50 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 00:29:28 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Ping timeout: 252 seconds) |
| 00:30:34 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 00:31:07 | → | FinnElija joins (~finn_elij@user/finn-elija/x-0085643) |
| 00:31:08 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 00:37:18 | → | maroloccio joins (~marolocci@89-172-7-22.adsl.net.t-com.hr) |
| 00:38:45 | ← | Izem parts (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Good Bye) |
| 00:40:54 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 00:41:28 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 00:41:39 | → | Igloo joins (~ian@matrix.chaos.earth.li) |
| 00:42:37 | <justsomeguy> | I felt the same way when reading about "stateless" "declarative" configuration management platforms. |
| 00:43:53 | × | cuz quits (~user@2601:182:cc02:8b0:88fe:7ac8:b1af:1fac) (Ping timeout: 264 seconds) |
| 00:45:12 | <Cale> | You really need a way to structure the state in large interactive applications a bit better. Having the top level need to "know about" everything in the entire application is really not okay past a certain point. |
| 00:46:25 | <Cale> | I think the right thing is for the accumulation of any given piece of state to happen just above every part of the application that cares about it, and no higher up than that. |
| 00:47:03 | <Cale> | At least, that's a decent rule of thumb. |
| 00:50:00 | <Cale> | "Everything potentially depends on everything else" is still bad, even if you can describe the relationship through time using a pure function. |
| 00:51:14 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 00:51:48 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 00:57:21 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 01:01:25 | → | lavaman joins (~lavaman@98.38.249.169) |
| 01:01:34 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:02:08 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:02:43 | × | Guest4814 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 01:03:40 | → | chris joins (~chris@81.96.113.213) |
| 01:03:44 | chris | is now known as Guest8879 |
| 01:06:46 | <sm> | +1! |
| 01:08:05 | × | Guest8879 quits (~chris@81.96.113.213) (Ping timeout: 252 seconds) |
| 01:11:16 | × | waleee quits (~waleee@h-98-128-228-119.na.cust.bahnhof.se) (Ping timeout: 252 seconds) |
| 01:11:29 | × | xff0x quits (~xff0x@83.236.31.114) (Ping timeout: 264 seconds) |
| 01:11:50 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 246 seconds) |
| 01:11:54 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:12:28 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:13:16 | → | xff0x joins (~xff0x@2001:1a81:53a2:cb00:c07c:d089:8b2f:814c) |
| 01:22:13 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:22:30 | × | alx741 quits (~alx741@186.178.109.159) (Quit: alx741) |
| 01:22:47 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:23:49 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 01:25:08 | × | cheater quits (~Username@user/cheater) (Ping timeout: 246 seconds) |
| 01:26:33 | → | neurocyte0133 joins (~neurocyte@212.232.95.106) |
| 01:26:33 | × | neurocyte0133 quits (~neurocyte@212.232.95.106) (Changing host) |
| 01:26:33 | → | neurocyte0133 joins (~neurocyte@user/neurocyte) |
| 01:28:54 | × | neurocyte013 quits (~neurocyte@user/neurocyte) (Ping timeout: 260 seconds) |
| 01:28:54 | neurocyte0133 | is now known as neurocyte013 |
| 01:30:30 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 01:31:55 | → | cheater joins (~Username@user/cheater) |
| 01:32:33 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:33:07 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:33:52 | <justsomeguy> | I think I've just started keeping a list of maintenance programmer adages, starting with your quote :^) |
| 01:41:49 | × | brettgilio quits (~brettgili@x-node.gq) (Quit: Leaving...) |
| 01:42:53 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:42:56 | → | brettgilio joins (~brettgili@x-node.gq) |
| 01:43:28 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:53:14 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 01:53:50 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 01:58:27 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 02:00:52 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 02:03:06 | → | favonia joins (~favonia@user/favonia) |
| 02:06:51 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 02:09:06 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 02:09:31 | × | Jonno_FTW quits (~come@api.carswap.me) (Changing host) |
| 02:09:31 | → | Jonno_FTW joins (~come@user/jonno-ftw/x-0835346) |
| 02:10:48 | × | azimut_ quits (~azimut@gateway/tor-sasl/azimut) (Ping timeout: 276 seconds) |
| 02:16:41 | × | yinghua quits (~yinghua@2800:2121:1400:1db:3d91:483:36a2:ad4f) (Quit: Leaving) |
| 02:16:48 | × | td_ quits (~td@muedsl-82-207-238-087.citykom.de) (Ping timeout: 268 seconds) |
| 02:18:20 | → | td_ joins (~td@muedsl-82-207-238-060.citykom.de) |
| 02:18:50 | × | tommd quits (~tommd@75-164-130-101.ptld.qwest.net) (Ping timeout: 260 seconds) |
| 02:19:01 | → | chris joins (~chris@81.96.113.213) |
| 02:19:05 | chris | is now known as Guest3810 |
| 02:20:11 | × | Guest3810 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 02:23:44 | → | azimut joins (~azimut@gateway/tor-sasl/azimut) |
| 02:27:11 | × | lavaman quits (~lavaman@98.38.249.169) (Remote host closed the connection) |
| 02:30:02 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 252 seconds) |
| 02:36:41 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 264 seconds) |
| 02:37:40 | × | Katarushisu quits (~Katarushi@cpc147334-finc20-2-0-cust27.4-2.cable.virginm.net) (Ping timeout: 240 seconds) |
| 02:39:14 | → | xiongxin joins (~quassel@119.123.103.94) |
| 02:42:19 | → | chris joins (~chris@81.96.113.213) |
| 02:42:23 | chris | is now known as Guest8457 |
| 02:43:17 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 02:43:54 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 02:44:53 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Ping timeout: 252 seconds) |
| 02:45:29 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 02:46:29 | → | FinnElija joins (~finn_elij@user/finn-elija/x-0085643) |
| 02:50:23 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 02:53:10 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 02:53:10 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 02:53:10 | → | wroathe joins (~wroathe@user/wroathe) |
| 02:54:37 | → | Katarushisu joins (~Katarushi@cpc147334-finc20-2-0-cust27.4-2.cable.virginm.net) |
| 02:57:41 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 264 seconds) |
| 02:57:41 | → | lavaman joins (~lavaman@98.38.249.169) |
| 02:58:22 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 03:02:29 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 264 seconds) |
| 03:06:53 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 03:07:14 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 03:11:53 | × | hiruji` quits (~hiruji@2606:6080:1001:f:ed79:9361:ea0e:3e88) (Ping timeout: 246 seconds) |
| 03:14:24 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 03:15:23 | → | Izem joins (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 03:16:57 | × | statusbot quits (~statusbot@ec2-34-198-122-184.compute-1.amazonaws.com) (Read error: Connection reset by peer) |
| 03:17:03 | → | statusbot1 joins (~statusbot@ec2-34-198-122-184.compute-1.amazonaws.com) |
| 03:17:29 | → | wroathe joins (~wroathe@user/wroathe) |
| 03:19:58 | × | raehik quits (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 252 seconds) |
| 03:22:59 | → | cjb41988 joins (~cjbayliss@user/cjb) |
| 03:23:20 | × | cjb41988 quits (~cjbayliss@user/cjb) (Client Quit) |
| 03:24:08 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 03:24:43 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 03:24:50 | → | cjb84397 joins (~cjbayliss@user/cjb) |
| 03:25:15 | cjb | is now known as Guest2446 |
| 03:25:15 | cjb84397 | is now known as cjb |
| 03:25:16 | × | Guest2446 quits (~cjbayliss@user/cjb) (Ping timeout: 260 seconds) |
| 03:26:00 | → | wei2912 joins (~wei2912@112.199.250.21) |
| 03:32:37 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 03:32:57 | × | justsomeguy quits (~justsomeg@user/justsomeguy) (Quit: WeeChat 3.2) |
| 03:34:29 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 03:35:03 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 03:35:17 | → | hiruji joins (~hiruji@user/hiruji) |
| 03:37:17 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 264 seconds) |
| 03:38:07 | × | juhp quits (~juhp@bb42-60-204-249.singnet.com.sg) (Ping timeout: 265 seconds) |
| 03:39:53 | × | machinedgod quits (~machinedg@135-23-192-217.cpe.pppoe.ca) (Ping timeout: 246 seconds) |
| 03:43:48 | ← | Izem parts (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Good Bye) |
| 03:46:03 | × | [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Remote host closed the connection) |
| 03:46:16 | → | favonia joins (~favonia@user/favonia) |
| 03:47:16 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 03:47:50 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 03:51:53 | × | Guest8457 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 03:55:48 | → | sagax joins (~sagax_nb@user/sagax) |
| 03:57:29 | → | neo1 joins (~neo3@cpe-292712.ip.primehome.com) |
| 03:57:34 | × | zebrag quits (~chris@user/zebrag) (Quit: Konversation terminated!) |
| 03:57:37 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 03:58:10 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:03:16 | → | Izem joins (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 04:07:56 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 04:08:31 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:14:51 | × | Guest372 quits (~xxx@47.245.54.240) (Remote host closed the connection) |
| 04:15:58 | × | albet70 quits (~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection) |
| 04:15:58 | → | Guest372 joins (~xxx@47.245.54.240) |
| 04:17:05 | → | albet70 joins (~xxx@2400:8902::f03c:92ff:fe60:98d8) |
| 04:19:34 | × | slowButPresent quits (~slowButPr@user/slowbutpresent) (Quit: leaving) |
| 04:19:53 | × | maroloccio quits (~marolocci@89-172-7-22.adsl.net.t-com.hr) (Ping timeout: 264 seconds) |
| 04:21:50 | → | maroloccio joins (~marolocci@93-142-92-177.adsl.net.t-com.hr) |
| 04:24:08 | → | ubert joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 04:25:15 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 04:25:49 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:30:33 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 04:33:05 | × | doyougnu quits (~user@c-73-25-202-122.hsd1.or.comcast.net) (Ping timeout: 264 seconds) |
| 04:35:35 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 04:36:05 | × | xiongxin quits (~quassel@119.123.103.94) (Ping timeout: 264 seconds) |
| 04:36:10 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:39:38 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 04:44:31 | × | shriekingnoise quits (~shrieking@186.137.144.80) (Quit: Quit) |
| 04:45:56 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 04:46:30 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:48:02 | → | lavaman joins (~lavaman@98.38.249.169) |
| 04:49:20 | <Izem> | Are the items in parentheses sections? `showsTree (Branch l r) = ('<':) . showsTree l . ('|':) . showsTree r . ('>':)` |
| 04:50:10 | <awpr> | yes, operator sections of `(:)` |
| 04:50:59 | <awpr> | they could also be replaced with `showChar '<'`, for example |
| 04:51:23 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds) |
| 04:52:37 | → | xiongxin joins (~quassel@119.123.103.94) |
| 04:52:53 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 264 seconds) |
| 04:56:03 | × | flouflou quits (~flouflou@modemcable032.110-177-173.mc.videotron.ca) (Quit: WeeChat 3.2) |
| 04:56:16 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 04:56:50 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 04:57:05 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 04:59:16 | <jle`> | Izem: if it's easier to see, you can write it as ('<' :) . showsTree l . ('|' :) . showsTree r . ('>' :) |
| 04:59:49 | <Izem> | yeah, good call |
| 05:00:08 | <Izem> | (in this case not much difference because my client does not use monospace characters) |
| 05:00:19 | <jle`> | i'll admit the '<': four symbols in a row did throw me off |
| 05:00:31 | <jle`> | despite writing haskell for a while now |
| 05:04:48 | <Izem> | I'll take a note when I write "Elements of Style" for Haskell ;) |
| 05:05:44 | × | Izem quits (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Quit: Izem) |
| 05:06:36 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 05:07:09 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 05:07:17 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 05:07:43 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 05:07:43 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 05:07:43 | → | wroathe joins (~wroathe@user/wroathe) |
| 05:08:50 | → | mikoto-chan joins (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) |
| 05:08:53 | → | Guest68 joins (~Guest68@103.121.152.207) |
| 05:12:17 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds) |
| 05:13:56 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 252 seconds) |
| 05:21:18 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 05:26:53 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 05:27:27 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 05:31:00 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 05:35:01 | × | cjb quits (~cjbayliss@user/cjb) () |
| 05:37:12 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 05:37:38 | → | juhp joins (~juhp@128.106.188.220) |
| 05:37:46 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 05:44:11 | <Axman6> | > let (<') a b = a <> b in "hello"<'" "<'"world" |
| 05:44:13 | <lambdabot> | <hint>:1:8: error: parse error on input ‘)’ |
| 05:44:14 | × | tzh quits (~tzh@c-24-21-73-154.hsd1.wa.comcast.net) (Quit: zzz) |
| 05:44:44 | <Axman6> | pretty happy that didn't work tbh |
| 05:45:39 | <ldlework> | > let (<:) a b = a < b in "hello" <: " " <: "world" |
| 05:45:40 | <lambdabot> | error: |
| 05:45:40 | <lambdabot> | • Couldn't match expected type ‘Bool’ with actual type ‘[Char]’ |
| 05:45:40 | <lambdabot> | • In the second argument of ‘(<:)’, namely ‘"world"’ |
| 05:46:18 | <ldlework> | > let (:<<) a b = a < b in "hello" :<< " " :<< "world" |
| 05:46:20 | <lambdabot> | error: |
| 05:46:20 | <lambdabot> | Not in scope: data constructor ‘:<<’ |
| 05:46:20 | <lambdabot> | Perhaps you meant one of these: |
| 05:46:26 | ldlework | shrugs |
| 05:46:44 | <ldlework> | oops |
| 05:46:52 | <ldlework> | > let (:<<) a b = a <> b in "hello" :<< " " :<< "world" |
| 05:46:53 | <lambdabot> | error: |
| 05:46:53 | <lambdabot> | Not in scope: data constructor ‘:<<’ |
| 05:46:53 | <lambdabot> | Perhaps you meant one of these: |
| 05:46:57 | ldlework | shrugs |
| 05:47:03 | <Axman6> | can't start functions with : |
| 05:47:13 | <Axman6> | only constructors |
| 05:47:21 | <ldlework> | > let (<<:) a b = a <> b in "hello" <<: " " <<: "world" |
| 05:47:22 | <lambdabot> | "hello world" |
| 05:47:26 | <ldlework> | \o/ |
| 05:47:45 | <Axman6> | stop making the C++ devs feel comfortable |
| 05:48:06 | <ldlework> | a friend of mine was dissing haskell because of all the wierd operators |
| 05:48:19 | <ldlework> | and i'm like, dude, they're just functions, with non-alphanumeric names, that can be called infix |
| 05:48:27 | <ldlework> | eventually he reduced his argument to "the names are dumb" |
| 05:48:39 | <ldlework> | hehe |
| 05:48:59 | → | takuan joins (~takuan@178-116-218-225.access.telenet.be) |
| 05:50:32 | <awpr> | tbf some of the names can get pretty crazy... `<<%@~` is a real operator in `lens` |
| 05:51:08 | <Axman6> | but is a completely consistent operator, and I can probably figure out what it does even without its type |
| 05:51:09 | <awpr> | I'm sure it means something if you've learned the symbolic etymology of the lens operators, but I haven't |
| 05:51:13 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) (Remote host closed the connection) |
| 05:51:40 | <awpr> | from scrolling I've gathered the @ is an indexed variant |
| 05:51:41 | × | mikoto-chan quits (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) (Ping timeout: 264 seconds) |
| 05:51:47 | → | Null_A joins (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) |
| 05:51:58 | <Axman6> | ~ means apply a function, @ I think means apply to an indexed lens, and I thing << means return the value before the function was applied that the optic pointed to |
| 05:52:16 | <Axman6> | % :t (<<%@~) |
| 05:52:16 | <yahb> | Axman6: Over (Indexed i) ((,) a) s t a b -> (i -> a -> b) -> s -> (a, t) |
| 05:53:37 | <Axman6> | yep - an indexed lens pointing to an a, a function whicht akes the index and the a and produces a b, that b is set in s to give a t and the original a is returned. Generalised x++ where you can choose what ++ is and change the type |
| 05:54:27 | <Axman6> | jackdk will remember the day I replaced five lines of code using MonadState with a single line using the stateful version of this function which ended up being clearer too (IMO) |
| 05:54:39 | <Axman6> | % :t (<<%@=) |
| 05:54:39 | <yahb> | Axman6: MonadState s m => Over (Indexed i) ((,) a) s s a b -> (i -> a -> b) -> m a |
| 05:55:32 | <jackdk> | oh yeah, indexed monadic state update, returning original result. The power of a consistent symbol language |
| 06:00:50 | × | Guest68 quits (~Guest68@103.121.152.207) (Quit: Client closed) |
| 06:00:54 | × | Null_A quits (~null_a@2601:645:8700:2290:6daa:6a79:97ab:557) () |
| 06:06:41 | × | xiongxin quits (~quassel@119.123.103.94) (Ping timeout: 264 seconds) |
| 06:06:57 | → | xiongxin joins (~quassel@113.116.32.188) |
| 06:13:19 | → | kuribas joins (~user@ptr-25vy0i747grimuk7ofw.18120a2.ip6.access.telenet.be) |
| 06:15:01 | → | lortabac joins (~lortabac@2a01:e0a:541:b8f0:4252:bf51:4908:8ea0) |
| 06:17:13 | → | bgamari_ joins (~bgamari@64.223.239.239) |
| 06:17:25 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 06:17:39 | → | juhp joins (~juhp@128.106.188.220) |
| 06:18:42 | × | bgamari quits (~bgamari@71.241.201.27) (Ping timeout: 260 seconds) |
| 06:26:45 | <awpr> | `profunctors` package synopsis: "Profunctors", package description: "Profunctors." |
| 06:27:09 | <awpr> | cabal has a warning when uploading packages, "the description should be longer than the synopsis" :D |
| 06:27:53 | × | xiongxin quits (~quassel@113.116.32.188) (Ping timeout: 246 seconds) |
| 06:31:23 | × | neurocyte013 quits (~neurocyte@user/neurocyte) (Ping timeout: 246 seconds) |
| 06:32:52 | → | qbt joins (~edun@user/edun) |
| 06:33:56 | → | alzgh joins (~alzgh@user/alzgh) |
| 06:40:34 | → | tromp joins (~textual@dhcp-077-249-230-040.chello.nl) |
| 06:43:11 | <ldlework> | awpr: I think they meant more like "functor" "monoid" etc |
| 06:44:08 | <ldlework> | Which of course are not the names of the operators, but I knew what they meant. |
| 06:47:05 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 06:47:53 | <[exa]> | awpr: that's mean, they made such an effort with the '.' |
| 06:49:15 | → | Gurkenglas joins (~Gurkengla@dslb-002-207-014-195.002.207.pools.vodafone-ip.de) |
| 06:50:57 | → | vaucouleur joins (~vaucouleu@78.194.70.105) |
| 06:51:50 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 06:52:39 | <c_wraith> | Honestly, the profunctors package is in an awkward spot. It would be in base, if it wasn't for the usefulness of #. and .# |
| 06:52:53 | <c_wraith> | No one quite wants to commit to putting hacks like that in base |
| 06:53:11 | → | xiongxin joins (~quassel@119.123.103.94) |
| 06:53:24 | <ldlework> | profunctors - must be something to do with lifing a function over structure, but what |
| 06:53:51 | <ldlework> | maybe they get paid to lift, that's why they're "pro" |
| 06:54:35 | <c_wraith> | Profunctors are function-shaped functors. Contravariant in one type variable, covariant in the other. |
| 06:54:39 | → | dschrempf joins (~dominik@070-207.dynamic.dsl.fonira.net) |
| 06:54:58 | <awpr> | profunctors are just functors from op(Hask) x Hask to Hask, what's the problem? |
| 06:55:45 | <ldlework> | :S |
| 06:55:51 | <awpr> | (I've always wanted to write my own needlessly inscrutable "what's the problem?" statement!) |
| 06:56:00 | <ldlework> | function-shaped functors? But functors are already functions being lifted over structure. |
| 06:56:18 | <ldlework> | Or do we mean, that the lhs of fmap is a function returning a function? |
| 06:56:25 | <c_wraith> | neither. |
| 06:56:28 | <ldlework> | I tried. |
| 06:57:04 | <c_wraith> | It means that in Profunctor p => p a b, a is negative and b is positive, and you can map over either appropriately |
| 06:57:19 | <c_wraith> | functions are a trivial example of that. |
| 06:57:30 | <ldlework> | what's meant by negative/positive? |
| 06:57:54 | <ldlework> | Or are we talking about something like Either's Left/Right? |
| 06:58:06 | <c_wraith> | Nah, Either is positive in both |
| 06:58:16 | <ldlework> | o_O |
| 06:58:16 | <c_wraith> | that is, it can produce a value of those types |
| 06:58:27 | <c_wraith> | it produces trivially by containing one of them. |
| 06:58:45 | <c_wraith> | A type in a negative position is being consumed |
| 06:58:56 | <c_wraith> | which basically means "an argument to a function" |
| 06:59:15 | <ldlework> | So you're saying `b` is the type being produced, `a` is the type we're computing over? |
| 06:59:33 | <c_wraith> | `a` is being consumed. |
| 06:59:44 | <ldlework> | that's what i meant by being computed over I guess |
| 06:59:49 | <ldlework> | not sure what other sense there is |
| 06:59:53 | <c_wraith> | There's no guarantee it's related to the b value |
| 07:00:14 | <ldlework> | Is there a trivial list/string example |
| 07:00:20 | <c_wraith> | like... data Z a b = Z (a -> String) (Int -> b) |
| 07:00:33 | <c_wraith> | there's no relationship between the a values and the b values |
| 07:00:46 | <c_wraith> | they just are the right sorts of things |
| 07:00:46 | × | vaucouleur quits (~vaucouleu@78.194.70.105) (Remote host closed the connection) |
| 07:00:52 | <ldlework> | Then what are we doing with them |
| 07:01:01 | <c_wraith> | Profunctor doesn't care. |
| 07:01:08 | <c_wraith> | It just lets you map over each |
| 07:01:22 | <ldlework> | How do you map over a function |
| 07:01:56 | <ldlework> | IIRC, that just means to map over its output value right? |
| 07:02:11 | <c_wraith> | actually, let me simplify that. |
| 07:02:14 | <ldlework> | OK |
| 07:02:20 | <c_wraith> | data Z a b = Z (a -> String) b |
| 07:02:40 | <ldlework> | So would profunctor call a, disregard the string, and then return b? |
| 07:02:52 | <c_wraith> | No, the a and b type variables are totally separate. |
| 07:02:56 | × | nctcf^ quits (~nctcf@12.203.127.82) (Remote host closed the connection) |
| 07:03:05 | <c_wraith> | Profunctor does not assume they're related. |
| 07:03:07 | <ldlework> | they're not related in my description |
| 07:03:17 | <c_wraith> | calling a function assumes they're related. |
| 07:03:27 | <ldlework> | Z somFun someConst |
| 07:03:35 | <ldlework> | someFun someA |
| 07:03:37 | <ldlework> | then just return b |
| 07:03:40 | <ldlework> | return someConst |
| 07:03:43 | <ldlework> | how are they related? |
| 07:04:30 | <ldlework> | i guess there's no point in calling `someFun someA` if it's output isn't used, and it has no effects though? |
| 07:04:39 | <c_wraith> | exactly. That's why it doesn't do that. |
| 07:05:32 | <ldlework> | I should probably learn what contravariance and covariance are |
| 07:05:43 | <c_wraith> | it's basically just the direction of mapping. |
| 07:06:33 | <c_wraith> | dimap :: (a -> b) -> (c -> d) -> Z b c -> Z a d ; dimap f g (Z h x) = Z (h . f) (g x) |
| 07:07:21 | <c_wraith> | Contravariant means the map goes backwards. |
| 07:08:02 | <c_wraith> | You see how there's an (a -> b) argument, but the type change is Z *b* c -> Z *a* d? |
| 07:08:34 | <c_wraith> | the types change in the opposite direction as the conversion function |
| 07:08:41 | <ldlework> | contramap :: (a0 -> a1) -> f a1 -> f a0 |
| 07:08:44 | <ldlework> | this is confusing indeed |
| 07:09:03 | <c_wraith> | It only works with things that are function arguments or phantom |
| 07:09:32 | × | neo1 quits (~neo3@cpe-292712.ip.primehome.com) (Read error: Connection reset by peer) |
| 07:10:23 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 07:10:24 | <ldlework> | I think I need to better my understanding of the Functor of functions |
| 07:10:56 | <c_wraith> | write a Functor instance for data F a b = F (a -> b) |
| 07:11:19 | <c_wraith> | or newtype, whatever :) |
| 07:12:09 | → | chele joins (~chele@user/chele) |
| 07:14:46 | <Guest372> | :t withFile |
| 07:14:47 | <lambdabot> | error: |
| 07:14:47 | <lambdabot> | • Variable not in scope: withFile |
| 07:14:47 | <lambdabot> | • Perhaps you meant one of these: |
| 07:17:05 | <Guest372> | withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r, why it uses (Handle -> IO r) -> IO r? not just IO r? |
| 07:17:18 | → | neo1 joins (~neo3@cpe-292712.ip.primehome.com) |
| 07:17:32 | <c_wraith> | because the point is it closes the file when the function you pass to it completes |
| 07:17:52 | <Guest372> | or just ContT r IO Handle? |
| 07:17:53 | → | max22- joins (~maxime@2a01cb08833598000f1fa44417d80ccf.ipv6.abo.wanadoo.fr) |
| 07:18:11 | <c_wraith> | Because Codensity IO Handle is better. :P |
| 07:18:19 | → | dhouthoo joins (~dhouthoo@178-117-36-167.access.telenet.be) |
| 07:19:05 | <Guest372> | close the file by the function you pass it or withFile itself? |
| 07:19:30 | <c_wraith> | withFile closes the file when the function passed to it exits - normally or via exception |
| 07:19:33 | → | jstolarek joins (~jstolarek@erx128.neoplus.adsl.tpnet.pl) |
| 07:19:52 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 07:20:25 | <Guest372> | aha, it will retur to withFile, that's I dont know |
| 07:20:31 | <c_wraith> | And you're right about ContT being usable to flip that control flow back around. http://blog.sigfpe.com/2011/10/quick-and-dirty-reinversion-of-control.html |
| 07:20:31 | <Guest372> | return |
| 07:20:51 | → | acidjnk joins (~acidjnk@p200300d0c703cb44319f4c33bc64626e.dip0.t-ipconnect.de) |
| 07:21:02 | <c_wraith> | Codensity is a slightly less expressive monad that can be used in the same way: https://hackage.haskell.org/package/kan-extensions-5.2.3/docs/Control-Monad-Codensity.html#t:Codensity |
| 07:24:02 | → | Guest7264 joins (~Guest72@117.223.48.235) |
| 07:24:14 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 246 seconds) |
| 07:24:16 | <Axman6> | but if you use ContT, the file will remain open until you run runContT right? |
| 07:24:33 | <Axman6> | so if you need timely file closure, ContT is not the right thing to do |
| 07:24:35 | <awpr> | it'll be opened and closed inside the runContT |
| 07:24:48 | <c_wraith> | I mean, withFile isn't the right thing to do if you need timely file closure either |
| 07:25:04 | <Axman6> | it is if you want the file to be closed before returning the r |
| 07:25:15 | <Axman6> | which is not what will happen with ContT |
| 07:25:48 | <c_wraith> | ContT doesn't change any logic |
| 07:25:59 | <c_wraith> | It just lets you escape nesting |
| 07:26:10 | × | Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer) |
| 07:26:17 | <c_wraith> | If you don't want nested logic, don't use it |
| 07:26:39 | <Axman6> | Don't you end up with the continuation that is passed to withFile being the entire rest of the ContT computation? |
| 07:27:01 | <c_wraith> | Just like you end up needing to pass the entire function that processes the Handle to withFile |
| 07:27:07 | <c_wraith> | It's the same thing |
| 07:27:29 | <awpr> | oh, you're picturing using ContT as the monad for the entirety of some big chunk of the program |
| 07:27:51 | <awpr> | yeah, that's how you get "open everything and release it all on exit" |
| 07:28:59 | <Axman6> | do { withFile "foo" RW (\h -> hPut h "Hello!"); putStrLn "File is now closed") } vs do { h <- ContT (withFile "foo" RW); liftIO (hPut "foo"); putStrLn "File is still open here" }? |
| 07:29:20 | <Axman6> | missing a liftIO but you get it |
| 07:29:24 | <awpr> | yes, that's why you shouldn't use ContT that way :) |
| 07:30:00 | <awpr> | if that's gonna be the return type of a withFile-alike, it should be used in as-small-as-possible ContT blocks wrapped in runContT |
| 07:30:18 | <c_wraith> | You only really want to use it on something like withFile if you need multiple handles open at the same time to do something. |
| 07:30:28 | <awpr> | +1 exactly |
| 07:30:35 | <c_wraith> | And you don't want to write syntactically nested functions for it |
| 07:31:02 | → | rond_ joins (~rond_@2a02:a31a:a23c:f480:2fd7:e087:5546:a438) |
| 07:31:09 | <awpr> | can think of ContT/Codensity as the monad of nested resource scopes in this context |
| 07:31:33 | <c_wraith> | I've used them that way for FFI code. |
| 07:31:58 | <awpr> | yeah, pretty great for that. I've _tried_ to use IxContT too, but it got tedious |
| 07:33:31 | <Axman6> | I wou;dn't mind reading more about that technique, got any good links? |
| 07:33:40 | <ldlework> | you all are on another level |
| 07:34:20 | <ldlework> | really glad I spent 15 years doing Python, real glad |
| 07:34:35 | <Axman6> | Now you have 15 years of bad ideas to unlearn though ;) |
| 07:34:44 | <ldlework> | Yeah there was an /s there |
| 07:34:47 | <Guest372> | about withFile s result type IO r, its coming from Handle -> IO r or withFile itself? |
| 07:35:02 | <Axman6> | it can only come from the function you pass to it |
| 07:35:15 | <c_wraith> | eh, whatever. I spent like 12 years doing BASIC before learning other languages. Despite Dijkstra's remarks, the language wasn't actively harmful. |
| 07:35:31 | <Axman6> | there is no other possible way to return an r unless it throws an exception or never returns |
| 07:35:51 | <Guest372> | but withFile will get control after the functuin is done |
| 07:35:57 | <Axman6> | yes |
| 07:36:14 | <c_wraith> | But it stores the result of your function. Then it closes the file. Then it returns what it stored. |
| 07:36:38 | <Guest372> | why withFile doesn't return anything else, can it? |
| 07:36:48 | <Axman6> | withFile is basically: withFile path mode f = do {h <- openHandle mode path; r <- f h; closeHandle h; return r } |
| 07:37:13 | <c_wraith> | with some error handling thrown in, but that would just make it noisy and harder to read. |
| 07:37:17 | → | cfricke joins (~cfricke@user/cfricke) |
| 07:37:31 | <Axman6> | (It's actual implementation is very different but that semantically what it does if f doesn't throw any exceptions) |
| 07:37:48 | <Guest372> | can withFile return 0 or 1? |
| 07:37:58 | <Axman6> | only if the function you pass it does |
| 07:39:11 | <Guest372> | (Handle -> IO r) is a continuation, right? |
| 07:39:29 | <Axman6> | yes |
| 07:39:38 | <c_wraith> | well. not exactly. |
| 07:39:39 | <Guest372> | and that closeHandle h; return r is contiuation too? |
| 07:39:45 | <c_wraith> | it has the same type |
| 07:39:49 | <c_wraith> | but it isn't a tail call |
| 07:39:54 | <Axman6> | I wouldn't have said that, no |
| 07:40:35 | <Axman6> | note that the return type of withFile is determined by the function, or continuation, that you pass it |
| 07:40:37 | <Guest372> | that closeHandle and return is behind the contiuation |
| 07:40:53 | <Axman6> | I think you're over complicating this - read the colde I wrote a bove |
| 07:40:58 | <Axman6> | above* |
| 07:41:36 | <c_wraith> | I think you're conflating something with the type of a continuation vs... a continuation. |
| 07:41:58 | <Guest372> | confuse |
| 07:42:36 | <ldlework> | Guest372: welcome to the club |
| 07:42:42 | <ldlework> | we have drinks and snacks at the bar |
| 07:43:07 | <c_wraith> | You've got a baseline assumption that calling a continuation is the last thing a function does. |
| 07:43:26 | <c_wraith> | And that's fair - that's what a continuation *is* - where to go next. |
| 07:43:54 | <c_wraith> | But you've mistaken withFile for being an example of using a continuation because it has the same type as stuff that does |
| 07:44:09 | <c_wraith> | But it's different - it's more of a traditional callback |
| 07:44:11 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 246 seconds) |
| 07:45:00 | <Guest372> | but in that withFile code above, call f isn't the last thing to do, there are closeHandle |
| 07:45:10 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 07:45:13 | <ldlework> | Guest372: that's their point |
| 07:46:02 | <Cale> | I think it's fine to think of it as a continuation of sorts. After all, you can use the Cont/ContT monad to work with such withFoo-style functions and handle all the nesting for you. |
| 07:46:55 | <c_wraith> | it's fine until your definition of "continuation" forbids what it does, and you get confused. |
| 07:47:41 | <Guest372> | Handle -> IO r inside withFile is a cotinuation? |
| 07:47:41 | <Cale> | It's not an unbounded continuation-until-the-end-of-time sort of continuation, but one which specifies what happens up until the file gets closed (or whatever) |
| 07:49:32 | <Guest372> | more confused, withFile will call f to handle its Handle, and when f is done, control return to withFile, then withFile close Handle |
| 07:49:55 | <ldlework> | you don't seem confused at all! |
| 07:49:59 | <Guest372> | f is not the last thing withFile do |
| 07:50:10 | <Guest372> | f is a continuation? |
| 07:50:17 | <c_wraith> | if your definition of continuation includes "the last thing a function does", then no, it's not. |
| 07:50:22 | <ldlework> | lol |
| 07:50:34 | <c_wraith> | If you relax the definition as Cale suggested, then sure. |
| 07:51:11 | <Guest372> | whats the right definiton? |
| 07:51:26 | <Guest372> | that most people using |
| 07:52:23 | <awpr> | the ContT monad evidently uses the relaxed version. in the context of "CPS", it's the stricter version. I'm not sure I'd call either one "right" or "wrong", they're just two very similar concepts |
| 07:52:46 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 07:53:00 | → | juhp joins (~juhp@128.106.188.220) |
| 07:53:41 | <ldlework> | So when you use a function functor, you are basically transforming a function of `a -> z0` to `a -> z1` ? |
| 07:54:23 | <Guest372> | so turn that (Handle -> IO r) -> IO r to ContT r IO Handle, who will close the handle? withFile itself or ContT? |
| 07:54:35 | <ldlework> | Oh that makes sense because that's what function composition does too |
| 07:55:12 | <ldlework> | x :: a -> b, y:: b -> c, then y . x :: a -> c |
| 07:58:29 | <ldlework> | Hmm, I just got to the end of the section that concludes: `To put another way: The type constructor (->) a z is covariant in its second argument.` |
| 07:58:36 | <ldlework> | But I still dont understand what is meant by that. |
| 07:58:44 | × | Guest7264 quits (~Guest72@117.223.48.235) (Quit: Client closed) |
| 07:58:45 | <c_wraith> | all it means is that it maps "forwards" |
| 07:59:07 | <c_wraith> | (a -> b) -> T a -> T b |
| 07:59:26 | <c_wraith> | contravariant means the mapping goes backwards: (a -> b) -> T b -> T a |
| 07:59:41 | <c_wraith> | covariant is much more common |
| 07:59:54 | <ldlework> | how would the latter even work |
| 08:00:09 | <ldlework> | if you have a -> b, you need an `a` on hand to pass |
| 08:00:14 | <ldlework> | well a T a |
| 08:00:21 | <c_wraith> | Not necessarily true! |
| 08:00:22 | <ldlework> | but you got a T b instead |
| 08:00:46 | <c_wraith> | newtype Predicate a = P (a -> Bool) |
| 08:00:49 | <awpr> | `newtype Predicate a = Predicat |
| 08:00:55 | <awpr> | ^ aborted |
| 08:01:17 | <ldlework> | was that supposed to be clarifying? :P |
| 08:01:22 | <c_wraith> | You don't have a value of type a in a Predicate a |
| 08:01:35 | <c_wraith> | you have an empty spot that accepts an a |
| 08:02:01 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 08:02:07 | <c_wraith> | So a function of type (a -> b) transforms something going into the empty spot. |
| 08:02:43 | <ldlework> | I understand that a data type doesn't need to structurally compose every type in its type constructor |
| 08:02:51 | <ldlework> | But I feel I'm no closer to understanding the backwards case |
| 08:03:27 | <awpr> | maybe try implementing the forwards case for Predicate and see what goes wrong |
| 08:04:19 | <ldlework> | what would I be implementing? |
| 08:04:39 | <awpr> | `instance Functor Predicate` for example |
| 08:04:41 | <ldlework> | just a function like Predicate a -> T Bool -> T a |
| 08:04:50 | <ldlework> | oh so fmap |
| 08:04:57 | → | benin036932301 joins (~benin@183.82.205.89) |
| 08:05:06 | <Cale> | Guest372: Of course it will still be withFile, but that will happen at the end after pretty much the rest of the action you're runContT'ing executes, and things start to unravel. Basically, when you write do v <- withFoo; ... in the ContT monad, it's like withFoo (\v -> ...) |
| 08:05:55 | → | hendursa1 joins (~weechat@user/hendursaga) |
| 08:06:05 | × | phma quits (~phma@host-67-44-208-198.hnremote.net) (Read error: Connection reset by peer) |
| 08:06:47 | <Cale> | Stuff like sequence in the Cont monad can be really useful if you want to get hold of an entire list of resources all at once |
| 08:06:54 | <Cale> | :t runCont . sequence . map cont |
| 08:06:55 | <lambdabot> | [(a -> r) -> r] -> ([a] -> r) -> r |
| 08:07:00 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 08:07:01 | → | phma joins (~phma@host-67-44-208-5.hnremote.net) |
| 08:07:43 | <Cale> | ^^ take a list of withFoo-style functions, and a function which will get a list of their results, ... and basically nest them in the obvious way |
| 08:08:57 | × | hendursaga quits (~weechat@user/hendursaga) (Ping timeout: 276 seconds) |
| 08:09:15 | <Cale> | Of course, you could write this function by hand, but it'll be way harder to think about whether you got it right than this :) |
| 08:09:17 | <Guest372> | you mean when runCotT is done, withFile close the file? |
| 08:09:34 | <ldlework> | awpr: c_wraith: couldn't match type 'a' with 'b' in `instance Functor Pred where fmap f (P p) = P (f . p)` |
| 08:10:16 | <Cale> | Guest372: Pretty much, once the action is done, all the with-style stuff you ran along the way will start to unravel in the same way as if you'd nested it all by hand. |
| 08:10:34 | <ldlework> | I guess that's the problem you alluded to? |
| 08:10:48 | <awpr> | my brain hurts trying to see how that error corresponds to that code; is it actually `p . f`? |
| 08:10:55 | <Cale> | The Cont/ContT monad just takes care of the nesting for you, and makes it appear like it's flattened out |
| 08:11:34 | <awpr> | oh, nvm, I can see where that error came from |
| 08:11:42 | <Guest372> | Cale just like sugar syntax? nothing more? |
| 08:11:44 | <awpr> | so, not exactly the error I was alluding to |
| 08:11:55 | <ldlework> | awpr: http://logos.ldlework.com/caps/2021-09-21-08-11-52.png |
| 08:12:13 | <Cale> | Guest372: Well, as I demonstrated there with sequence, it buys you a little more than syntax sugar, because you get to use all the stuff that works in any monad |
| 08:12:26 | <ldlework> | awpr: where did i go wrong? |
| 08:12:35 | → | nschoe joins (~quassel@178.251.84.79) |
| 08:12:50 | <awpr> | so you've got an `a` in the type that you want to end up being a `b`; the `a` is the input to the `p` function |
| 08:12:56 | → | __monty__ joins (~toonn@user/toonn) |
| 08:13:28 | <awpr> | and you've got a function to apply, that you want to use to transform the `a` values, which are inputs to `p` |
| 08:13:53 | × | cfricke quits (~cfricke@user/cfricke) (Ping timeout: 264 seconds) |
| 08:15:50 | <ldlework> | awpr: so the inputs should go into ... `f`, which are then piped into `p`? |
| 08:15:56 | <awpr> | yep |
| 08:15:56 | <ldlework> | isn't that just function composition? |
| 08:16:09 | <awpr> | also yes, it's just the other order of function composition |
| 08:16:23 | <ldlework> | awpr: http://logos.ldlework.com/caps/2021-09-21-08-16-21.png |
| 08:17:10 | <awpr> | yeah, there's what I was expecting to see: in `fmap`, the `f` function is _backwards_ from what it'd need to be to be able to transform the `a` type |
| 08:17:25 | × | geekosaur quits (~geekosaur@xmonad/geekosaur) (Remote host closed the connection) |
| 08:17:46 | <awpr> | you have an `a -> b` and an `a -> Bool`, and they just don't fit together |
| 08:17:50 | → | geekosaur joins (~geekosaur@xmonad/geekosaur) |
| 08:17:51 | <ldlework> | awpr: oh, so this is why we need Profunctor and not just Functor? |
| 08:18:09 | <awpr> | well, in this particular case, Contravariant instead of Functor |
| 08:18:22 | <ldlework> | I see. |
| 08:18:42 | <awpr> | now try `contramap :: (b -> a) -> Pred a -> Pred b`, with the same definition, and it should work |
| 08:18:47 | <ldlework> | awpr: one day when you're not busy, want to collaborate on a draw.io diagram (or something) of the typeclass family tree? |
| 08:19:01 | <ldlework> | i haven't been able to find a substantial one |
| 08:19:12 | <awpr> | hmm, I thought there were a few of those scattered around |
| 08:19:25 | <ldlework> | i found a couple, but they are only a handful of typeclasses |
| 08:19:29 | <awpr> | https://wiki.haskell.org/Typeclassopedia |
| 08:19:36 | <awpr> | that has a pretty substantial one |
| 08:20:00 | <awpr> | hmm, no profunctor or contravariant, though |
| 08:20:08 | <ldlework> | I was just gonna say that :P |
| 08:20:30 | <ldlework> | awpr: would it be possible to generate this list from the haskell source code? |
| 08:20:39 | <ldlework> | using some dumb grep/python or whatever |
| 08:21:00 | <ldlework> | s/list/graph |
| 08:21:14 | <awpr> | maybe, but there can be cases where something is sort of a superclass but doesn't actually say so in code |
| 08:21:25 | <ldlework> | Oh rip |
| 08:21:25 | <awpr> | like Applicative => Monad used to be that way a long time ago |
| 08:21:30 | <ldlework> | Right |
| 08:21:38 | <ldlework> | And monoid => Semigroup? |
| 08:21:54 | <awpr> | yeah, in the other direction |
| 08:21:56 | <ldlework> | awpr: maybe it would get 80% there |
| 08:22:36 | <ldlework> | It'd also be kind of a map of what relations are left implicit today |
| 08:22:51 | <awpr> | I'm also not sure how to represent the relationship between e.g. Functor, Contravariant, Bifunctor, Profunctor, Functor10, etc. visually. they're all very closely connected, but not by any superclass relationships |
| 08:23:12 | <ldlework> | awpr: we can use different line types |
| 08:23:30 | <ldlework> | awpr: are you saying there'd be no way to automatically associate Functor and Contravariant (for example)? |
| 08:23:45 | <awpr> | yeah, not that I know of |
| 08:23:55 | <ldlework> | aww, dreams dying over here |
| 08:25:23 | <ldlework> | this idea of collaborating to make a full typeclass diagram has made me think of another idea, a realtime collaborative web-based PlantUML editor |
| 08:25:35 | <ldlework> | man that'd be dope |
| 08:26:26 | × | ubert quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Ping timeout: 252 seconds) |
| 08:26:28 | → | michalz joins (~michalz@185.246.204.33) |
| 08:27:09 | × | hnOsmium0001 quits (uid453710@id-453710.hampstead.irccloud.com) (Quit: Connection closed for inactivity) |
| 08:27:51 | <ldlework> | awpr: now i'm annoyed lol |
| 08:28:25 | <merijn> | contravariant functors and functors are kinda opposites |
| 08:28:42 | [exa] | feels category diagrams incoming |
| 08:28:45 | <merijn> | So you could have a mirror in the middle to "opposite world" and do that :p |
| 08:29:14 | <merijn> | ldlework: See also comonad (does coapplicative exist? Presumably, but I don't think I've seen it...) |
| 08:29:17 | <awpr> | yeah, we'd have to have product world and parametric world too though |
| 08:29:41 | <ldlework> | let's do it |
| 08:30:12 | ← | Guest372 parts (~xxx@47.245.54.240) () |
| 08:30:18 | <[exa]> | ldlework: uml kinda sucks for this stuff honestly, the major things are usually transformations and arrows, not objects |
| 08:30:23 | × | benin036932301 quits (~benin@183.82.205.89) (Ping timeout: 246 seconds) |
| 08:30:45 | <awpr> | yeah I think that kind of sums up my lack of optimism |
| 08:31:07 | <ldlework> | [exa]: It's just that PlanUML is convienent because of it's text-based format |
| 08:31:22 | <ldlework> | rather than dragging and clicking, i'm pretty sure it'd be sufficient to express some relationships |
| 08:31:27 | <[exa]> | ldlework: I can argue that ascii art is a better text based format :] |
| 08:31:35 | <awpr> | it'd be possible to throw things into a planar graph, but the useful relationships wouldn't be very visible |
| 08:31:49 | <[exa]> | ldlework: anyway there's a TeX package for drawing this already |
| 08:32:01 | <awpr> | a giant category theory diagram would do the trick, but it'd also be rather cluttered |
| 08:32:05 | <ldlework> | Yeah I definitely want to go setup TeX right now :P |
| 08:32:15 | <ldlework> | awpr: that's why there's zoom |
| 08:32:26 | <[exa]> | zoom doesn't work for brains |
| 08:32:47 | <[exa]> | you either get the idea at one level, or it's cluttered |
| 08:32:58 | → | ubert joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 08:32:59 | <ldlework> | mindmaps are pretty successful |
| 08:33:11 | <ldlework> | we're making really generalized claims about tools that are clearly helpful to many people |
| 08:33:18 | <[exa]> | yep. :] |
| 08:33:28 | <[exa]> | mindmaps are about not missing the relations, useful for sure |
| 08:33:46 | <[exa]> | still you don't remember "the shape of the mindmap" as something to guide your math/programming intuition right? |
| 08:33:59 | <ldlework> | if we had a big planar map of the typeclass relations with different arrow types, or whatever |
| 08:34:02 | <awpr> | if it could actually all fit into a pannable/zoomable map that labels category theory stuff with Haskell names, that'd be really cool. will have to think about whether it can be made to work |
| 08:34:12 | <ldlework> | it'd be clearly useful/valuable in getting a vista |
| 08:34:21 | <[exa]> | ldlework: did you see the one for number hierarchy? |
| 08:34:24 | <ldlework> | especially if they linked out to typeopedia resources, etc |
| 08:34:54 | <[exa]> | actually some dynamic graph drawing could be really cool |
| 08:35:04 | <awpr> | things get _really_ stratified though when you start trying to be honest about category theory concepts in Haskell, though |
| 08:35:04 | <ldlework> | awpr: if you'd be willing to help with the formal knowledge, I wouldn't be against exploring some custom options using React Flow |
| 08:35:19 | <ldlework> | I've built such things before |
| 08:35:39 | <ldlework> | Maybe we could do layers, where you could have controls on the right to toggle things on and off, etc |
| 08:36:05 | <awpr> | like a profunctor is a Hask-enriched functor from the product category OpHaskxHask to Hask, and then there are ProfunctorFunctors which treat those as objects of their own category |
| 08:36:15 | <ldlework> | awpr: in the end, i also have built things with threejs so if we needed to go three dimensional, it's a possibility :P |
| 08:37:32 | <awpr> | I do find myself trying to visually build this stuff up in my head all the time... could be really cool to have it all there in one place |
| 08:37:42 | <ldlework> | it really would be |
| 08:38:07 | → | benin036932301 joins (~benin@183.82.205.89) |
| 08:38:27 | <awpr> | need to let the idea braise for a while / find time to be able to work on it |
| 08:38:45 | <ldlework> | awpr: with plantuml, we could embed the lawful functions inside the objects too |
| 08:38:59 | <ldlework> | I'm gonna recreate the typopedia diagram in plantuml just as a salespitch |
| 08:40:04 | <[exa]> | ldlework: actually a nice opportunity to learn some haskell webbing, FRP or miso :D |
| 08:40:59 | <ldlework> | [exa]: if i was gonna build a custom explorer i'd love to go the haskell route, but with work, i'd just need to snap it out using the tech i'm really comfortable with |
| 08:41:04 | → | bitdex joins (~bitdex@gateway/tor-sasl/bitdex) |
| 08:41:33 | <ldlework> | I'd love to learn Reflex |
| 08:42:35 | <Cale> | ldlework: Nice! Let me know how it goes. |
| 08:44:49 | <Cale> | (I'm working for Obsidian Systems, and while Reflex is much more Ryan's doing than mine, it's definitely inspired by the work we did together on earlier FRP systems.) |
| 08:47:07 | <[exa]> | ldlework: it would be interesting to also have the instances around (they make the classes work, right?). I was always kinda wondering how (or if) to correctly draw stuff like `instance Monoid a => Monoid (r -> a)` in this scheme, which I'd find pretty useful |
| 08:49:49 | → | lavaman joins (~lavaman@98.38.249.169) |
| 08:50:50 | × | xiongxin quits (~quassel@119.123.103.94) (Ping timeout: 265 seconds) |
| 08:50:54 | → | xiongxin_ joins (~quassel@113.116.32.178) |
| 08:54:41 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 264 seconds) |
| 08:57:13 | <ldlework> | http://logos.ldlework.com/caps/2021-09-21-08-57-09.png |
| 08:57:19 | <ldlework> | Cale: [exa] awpr |
| 08:58:06 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 08:58:19 | → | juhp joins (~juhp@128.106.188.220) |
| 09:00:16 | <[exa]> | ldlework: perhaps there would be a github CI renderer for this so it can be shared reasonably |
| 09:00:38 | × | xiongxin_ quits (~quassel@113.116.32.178) (Ping timeout: 260 seconds) |
| 09:00:39 | <awpr> | looks pretty good for the Hask->Hask subset of the world |
| 09:00:57 | <ldlework> | there are a lot of options for styling, arrows, etc too |
| 09:01:00 | <ldlework> | labels, and so on |
| 09:01:35 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:283f:384b:ba74:f15c) (Remote host closed the connection) |
| 09:01:57 | <awpr> | things do start to go downhill slightly with all the dotted lines meaning different things, though -- e.g. Monoid -> Category is oidification, Applicative -> Traversal is like "this uses that", Monoid -> Applicative is "this is the tensor product used in constructing that", etc. |
| 09:03:27 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 09:03:27 | <merijn> | You do realise what happened the last time someone tried to make a single comprehensive document containing all math, yeah? :p |
| 09:03:45 | → | lavaman joins (~lavaman@98.38.249.169) |
| 09:03:53 | <awpr> | somebody invented more math? |
| 09:03:53 | × | lavaman quits (~lavaman@98.38.249.169) (Remote host closed the connection) |
| 09:04:05 | <ldlework> | merijn: I just want a useful resource to give a vista for new haskell programmers that's all :P |
| 09:04:07 | <ldlework> | (like me) |
| 09:04:25 | <ldlework> | awpr: we can have specifically styled lines to mean specific things |
| 09:06:07 | <awpr> | I've kinda gone off on a tangent into category theory land now. the UML-style diagram seems like it could be useful to a lot of people, but the thing I'm kinda excited about is a browseable category theory thing that points at some concrete thing and says e.g. "this is Functor" |
| 09:06:52 | <awpr> | the planar graph version is much more tractable, at least |
| 09:08:07 | awpr | just used the word "concrete" in a sentence about category theory... |
| 09:08:09 | <sshine> | awpr, someone invented a meta-proof-system. this is only natural. I suppose Gödel was the first one to show that any cool enough concept devolves into meta-programming. |
| 09:09:05 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Ping timeout: 264 seconds) |
| 09:11:32 | × | geekosaur quits (~geekosaur@xmonad/geekosaur) (Remote host closed the connection) |
| 09:13:13 | <awpr> | for now though I've got to get some sleep -- I'll keep thinking about whether the whole world can fit into a diagram |
| 09:14:47 | <ldlework> | http://logos.ldlework.com/caps/2021-09-21-09-14-43.png |
| 09:16:35 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 09:18:42 | <ldlework> | I can't find anything on "Apply" |
| 09:21:19 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 09:22:19 | <Taneb> | https://hackage.haskell.org/package/semigroupoids-5.3.2/docs/Data-Functor-Apply.html#g:2 ? |
| 09:26:22 | <merijn> | ldlework: Because Apply is mostly lawless nonsense >.> |
| 09:34:34 | → | lavaman joins (~lavaman@98.38.249.169) |
| 09:37:16 | <ldlework> | WIP https://i.imgur.com/oc17eZE.png |
| 09:38:59 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 246 seconds) |
| 09:39:28 | → | Brumaire joins (~quassel@37.165.26.197) |
| 09:41:32 | × | dschrempf quits (~dominik@070-207.dynamic.dsl.fonira.net) (Quit: WeeChat 3.2.1) |
| 09:42:54 | × | bastelfreak quits (~bastelfre@basteles-bastelknecht.bastelfreak.org) (Quit: WeeChat 3.2) |
| 09:44:44 | → | jacks2 joins (~bc8165b6@217.29.117.252) |
| 09:45:03 | <ldlework> | [exa]: Cale thoughts? |
| 09:45:32 | <jacks2> | hi. I want to put some haskell code in settings file that will be evaluated by haskell program. basically, I need to ship my program with ghci interpreter. what's the best way of achieving this? |
| 09:46:11 | <ldlework> | jacks2: have you considered dhall instead? |
| 09:46:17 | <jacks2> | (I don't care about security, this is a personal project used only by me) |
| 09:46:19 | → | bastelfreak joins (~bastelfre@basteles-bastelknecht.bastelfreak.org) |
| 09:46:39 | <ldlework> | jacks2: there is https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/extending_ghc.html |
| 09:46:54 | × | werneta quits (~werneta@70-142-214-115.lightspeed.irvnca.sbcglobal.net) (Remote host closed the connection) |
| 09:47:13 | <jacks2> | ldlework, it looks interesting, but I already have a working settings file in a different format, I just need a way to interpret strings as haskell code |
| 09:47:23 | <ldlework> | jacks2: look at the link I just sent :) |
| 09:47:52 | <jacks2> | oh this is part of ghc now? nice |
| 09:47:59 | <jacks2> | I recall using some third party library many years ago |
| 09:48:37 | <ldlework> | jacks2: tell me you're making an Ansible alternative, but with Haskell |
| 09:49:19 | <jacks2> | no :). just a quick and dirty program for my own use |
| 09:54:41 | → | kayprish joins (~kayprish@46.240.130.158) |
| 09:54:49 | <[exa]> | ldlework: I'm doing something else now sorry :D looks good but I guess it's gonna get really cluttered when you start completing it |
| 09:55:14 | <ldlework> | will just take massaging |
| 09:59:14 | → | mc47 joins (~mc47@xmonad/TheMC47) |
| 10:00:06 | → | on^ joins (~on@12.203.127.82) |
| 10:00:56 | × | maroloccio quits (~marolocci@93-142-92-177.adsl.net.t-com.hr) (Quit: WeeChat 3.0) |
| 10:02:31 | <maerwald> | ldlework: you mean propellor? |
| 10:02:46 | <maerwald> | (I don't recommend it) |
| 10:03:28 | <maerwald> | @hackage propellor |
| 10:03:29 | <lambdabot> | https://hackage.haskell.org/package/propellor |
| 10:03:49 | × | Brumaire quits (~quassel@37.165.26.197) (Ping timeout: 265 seconds) |
| 10:03:57 | <ldlework> | maerwald: https://github.com/dhall-lang/dhall-haskell |
| 10:04:20 | <maerwald> | ldlework: ? |
| 10:04:22 | <Cale> | ldlework: Nice, what are you using to draw the stuff? |
| 10:04:48 | <ldlework> | maerwald: I don't know what you meant by "you mean propeller?" |
| 10:04:53 | <ldlework> | maerwald: oh ansible alternative |
| 10:04:58 | <ldlework> | makes sense now :P |
| 10:05:04 | <ldlework> | Cale: plantuml |
| 10:05:59 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 252 seconds) |
| 10:06:34 | <dminuoso> | You're shipping 1GiB of a compiler just to be able to read a settings file? |
| 10:06:35 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:06:37 | <dminuoso> | Mmm. |
| 10:06:58 | <dminuoso> | Dhall would seem easier.. |
| 10:07:08 | × | kayprish quits (~kayprish@46.240.130.158) (Remote host closed the connection) |
| 10:07:17 | <ldlework> | :D |
| 10:11:53 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 246 seconds) |
| 10:12:05 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:17:29 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 10:17:41 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:22:44 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 246 seconds) |
| 10:23:17 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:25:03 | → | xiongxin joins (~quassel@119.123.102.205) |
| 10:30:05 | → | oxide joins (~lambda@user/oxide) |
| 10:33:41 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 10:34:48 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:34:49 | × | totbwf__ quits (sid402332@id-402332.uxbridge.irccloud.com) (Quit: Connection closed for inactivity) |
| 10:38:06 | × | econo quits (uid147250@user/econo) (Quit: Connection closed for inactivity) |
| 10:38:26 | × | bastelfreak quits (~bastelfre@basteles-bastelknecht.bastelfreak.org) (Quit: WeeChat 3.3) |
| 10:38:42 | → | bastelfreak joins (~bastelfre@basteles-bastelknecht.bastelfreak.org) |
| 10:39:10 | → | cfricke joins (~cfricke@user/cfricke) |
| 10:40:17 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 10:40:27 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:50:29 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 10:52:04 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 10:53:11 | × | neo1 quits (~neo3@cpe-292712.ip.primehome.com) (Ping timeout: 246 seconds) |
| 10:54:39 | <ldlework> | Is Monoid a (logical) superclass of Foldable? |
| 10:55:33 | <Las[m]> | No |
| 10:55:45 | <dminuoso> | They have different kinds, in fact. |
| 10:55:47 | <dminuoso> | % :k Foldable |
| 10:55:47 | <yahb> | dminuoso: (* -> *) -> Constraint |
| 10:55:47 | <Las[m]> | They don't have the same kind first of all |
| 10:55:49 | <dminuoso> | % :k Monoid |
| 10:55:49 | <yahb> | dminuoso: * -> Constraint |
| 10:56:19 | <dminuoso> | Though there is a sort of relationship. |
| 10:56:40 | <ldlework> | in https://wiki.haskell.org/wikiupload/d/df/Typeclassopedia-diagram.png what are the dashed lines indicating |
| 10:56:45 | <dminuoso> | % :t toList |
| 10:56:45 | <yahb> | dminuoso: Foldable t => t a -> [a] |
| 10:56:52 | <ldlework> | is it that functions of the typeclass use the other typeclass? |
| 10:57:00 | <dminuoso> | We can think this function as the spiritual embodiment of Foldable |
| 10:57:09 | <dminuoso> | And with some squinting we can think of lists as free monoids. |
| 10:57:18 | <dminuoso> | Is that perhaps the relationship you're after? |
| 10:57:38 | <ldlework> | dminuoso: I was just observing that some of Foldable's functions take Monoids |
| 10:57:44 | <dminuoso> | Yes, it's a good observation. |
| 10:57:56 | <ldlework> | fold :: Monoid m => t m -> m |
| 10:58:04 | <ldlework> | So I was thinking of including a relation in my graph for that |
| 10:58:29 | <dminuoso> | There's no straight relationship like that. |
| 10:58:51 | <ldlework> | straight relationship? |
| 10:59:27 | <dminuoso> | The best I can see is what I outlined earlier, thinking of `toList` as the (conceptual) characteristic method of Foldable, and thinking of a list as the free monoid. |
| 10:59:33 | <ldlework> | I wonder if I should include each typeclasses' kind in the graph |
| 10:59:53 | <ldlework> | dminuoso: what do you mean by "free" in "free monoid" |
| 11:00:10 | × | Chai-T-Rex quits (~ChaiTRex@user/chaitrex) (Remote host closed the connection) |
| 11:00:22 | <dminuoso> | "free" as in "without any extra luggage" |
| 11:00:32 | <dminuoso> | unrestricted/free |
| 11:00:38 | <dminuoso> | It's a term originating from math |
| 11:00:40 | → | Chai-T-Rex joins (~ChaiTRex@user/chaitrex) |
| 11:00:58 | → | alx741 joins (~alx741@186.178.109.159) |
| 11:02:29 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 11:02:29 | <ldlework> | dminuoso: would extra luggage be in the Semigroup direction, or the opposite direction of some other hypothetical typeclass that's a subclass of Monoid |
| 11:02:40 | <ldlework> | The latter right? |
| 11:02:54 | <dminuoso> | If you really want to know the gory details we'd have to dive a bit into category theory. |
| 11:03:06 | <dminuoso> | Let me try and think of a handwaving way to explain this |
| 11:03:39 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 11:03:57 | <ldlework> | dminuoso: I have a category theory friend, and he can explain how a car works by simplifying it down and using metaphors, but he cannot explain category theory without using jargon / using metaphors ^_^ |
| 11:04:00 | <dminuoso> | A `free something` is the bare essential `something` that satisfies its laws, but nothing extra. |
| 11:04:34 | <dminuoso> | A handwaving, perhaps suggestive way, is to think of a list as representing the mere monoidal structure |
| 11:04:54 | <ldlework> | dminuoso: so a Semigroup would be a `degenerate monoid`, a monoid would be a `free monoid` and something who's superclass was Monoid would be a `restricted monoid` ? |
| 11:05:02 | <dminuoso> | No rather |
| 11:05:13 | <dminuoso> | Take the monoid of natural numbers under addition |
| 11:05:18 | <ldlework> | Right |
| 11:05:36 | <ldlework> | Semigroup of natural numbers + 0 for identity |
| 11:05:43 | <dminuoso> | The monoid encompasses not just the operation (+) and its identity (0), but also the entirety of all elements. |
| 11:05:55 | <ldlework> | the "domain" |
| 11:06:01 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 11:06:07 | <dminuoso> | In category theory there's a lot of structure simply because we cant just ignore those numbers. |
| 11:06:28 | → | jespada joins (~jespada@2803:9800:9842:7a62:edd5:5e74:3ec2:1b19) |
| 11:06:55 | <dminuoso> | So we have these constructions in category theory that allow us to "forget structure", so if we forget as much about this monoid as possible, while still satisfying the monoidal laws |
| 11:07:25 | <dminuoso> | Sorry no that is wrong |
| 11:07:27 | <dminuoso> | So |
| 11:07:47 | <dminuoso> | ldlework: imagine a transformation from the naturals under addition to just the set of naturals. |
| 11:08:00 | <dminuoso> | ldlework: Notice how such a transformation would essentially "forget" about all the monoidal structure? |
| 11:08:13 | <ldlework> | dminuoso: It's like how a Monoid is a "restricted semigroup" since it is the "Semigroup with extra baggage" (identity), no? |
| 11:08:32 | <dminuoso> | Yes, absolutely. |
| 11:08:42 | <dminuoso> | But for this purpose, we intend to forget the entirety of the monoidal structure |
| 11:08:44 | <dminuoso> | not just the identity |
| 11:08:59 | <ldlework> | so the semigroup bits too |
| 11:09:02 | <dminuoso> | Yes. |
| 11:09:05 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 11:09:08 | <dminuoso> | Everything but the carrier set |
| 11:09:11 | <ldlework> | why are we forgetting structure? I lost the thread. |
| 11:09:18 | <dminuoso> | Dont worry about the details of why we do this. |
| 11:09:24 | <ldlework> | XD |
| 11:09:40 | <dminuoso> | We can make a construction, called a functor, that does this with any monoid |
| 11:09:42 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 11:09:54 | <dminuoso> | So given a particular monoid, it just strips away the monoidal structure and gives you back the carrier set |
| 11:10:11 | <ldlework> | well if you fmap'd id into the monoid |
| 11:10:13 | <ldlework> | right |
| 11:10:22 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Ping timeout: 260 seconds) |
| 11:10:41 | <dminuoso> | Note that the "functor" is a different functor from our Haskell thing. A functor is just a way to transform one category into another. In our case, the category of monoids to the category of sets. |
| 11:10:44 | <ldlework> | that would extract whatever is inside the structure |
| 11:10:52 | <ldlework> | mm |
| 11:10:57 | <dminuoso> | And we can also construct another functor in the other direction |
| 11:11:08 | <dminuoso> | That is intrinsically related |
| 11:11:17 | <dminuoso> | To the former functor (called the forgetful functor) |
| 11:11:18 | <ldlework> | Now you have a Groupoid right |
| 11:11:25 | <ldlework> | Since each morphism is an isomorphism |
| 11:11:26 | <dminuoso> | Well the question is what does that functor even do |
| 11:11:31 | <dminuoso> | So what we do is this: |
| 11:11:42 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 11:11:57 | <dminuoso> | That functor maps a given set to the monoid [a], under which the unit is [] and the binary operation is ++ |
| 11:12:00 | <dminuoso> | It can map *every* set this way |
| 11:12:17 | <dminuoso> | It turns out that these two functors have a deep relationship |
| 11:12:45 | <ldlework> | you're basically just saying |
| 11:12:49 | <ldlework> | you can put things into a list |
| 11:12:51 | <dminuoso> | The former is called a forgetful functor (forgetting monoidal structure), the latter is called a free functor (adding the *bare* monoidal structure back, with no extra baggage) |
| 11:12:55 | <ldlework> | and we can do list concatenation |
| 11:13:08 | <dminuoso> | We still have monoidal shape in list concatenation |
| 11:13:12 | <dminuoso> | but no meaning of that |
| 11:13:59 | <ldlework> | OK, so you're outlining that with regards to structure, we have a way of taking a set and putting it into structure or taking it out of structure |
| 11:14:27 | <ldlework> | where a set is some domain of values of a given type, like natural numbers |
| 11:14:31 | <dminuoso> | Well, we have a way of forgetting concrete monoidal structure back to a set, and a way of adding *bare/essential* monoidal structure to a set. |
| 11:14:39 | <dminuoso> | Sure, it could be any |
| 11:15:05 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 11:15:25 | <ldlework> | by emphasizing bare essential structure, you just mean, we're just putting the values back into the list (monoid), but no additional structure |
| 11:15:33 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 11:15:34 | <dminuoso> | This relationship between "free" and "forgetful" can be observed in Haskell, even. |
| 11:16:10 | <dminuoso> | If we call the forgetful functor `U` that strips away the monoidal structure, and `F` that free functor, we express that relationship as: |
| 11:16:19 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 265 seconds) |
| 11:16:23 | <dminuoso> | `F a -> b` is isomorphic to `a -> U b` |
| 11:17:15 | <dminuoso> | Now, again ignoring gory details: |
| 11:17:41 | → | Everything joins (~Everythin@37.115.210.35) |
| 11:17:51 | <dminuoso> | This eventually turns into Haskell by showing that `[a] -> b` being expressible by a function `a -> b` |
| 11:17:54 | <dminuoso> | % :t foldMap |
| 11:17:54 | <yahb> | dminuoso: (Foldable t, Monoid m) => (a -> m) -> t a -> m |
| 11:18:05 | <dminuoso> | If you set `t ~ []` |
| 11:18:18 | → | raehik joins (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) |
| 11:18:35 | × | wei2912 quits (~wei2912@112.199.250.21) (Quit: Lost terminal) |
| 11:18:57 | → | Brumaire joins (~quassel@37.165.2.61) |
| 11:19:23 | <Cajun> | so if you composed those functions ( `F a -> b` and `a -> U b` ) and assumed `a ~ b` you could get the "bare monoidal structure" from the forgetful functor? |
| 11:19:42 | <dminuoso> | Those are not regular functions. |
| 11:20:11 | <dminuoso> | Perhaps this was a bit misleading |
| 11:20:30 | <Cajun> | ah category theory functors where its just some type to another, not a function? |
| 11:20:50 | × | cheater quits (~Username@user/cheater) (Ping timeout: 246 seconds) |
| 11:25:16 | <dminuoso> | The thing is, `F` is implicitly there in Haskell |
| 11:25:54 | <dminuoso> | So we could roughly do this: |
| 11:25:59 | × | Brumaire quits (~quassel@37.165.2.61) (Ping timeout: 265 seconds) |
| 11:26:36 | <dminuoso> | % newtype Mon a = Mon [a]; instance Semigroup (Mon a) where Mon a <> Mon b = Mon (a ++ b); instance Monoid (Mon a) where mempty = Mon []; |
| 11:26:36 | <yahb> | dminuoso: ; <interactive>:53:90: error: parse error on input `instance' |
| 11:26:45 | <dminuoso> | % newtype Mon a = Mon [a] |
| 11:26:45 | <yahb> | dminuoso: |
| 11:26:49 | <dminuoso> | % nstance Semigroup (Mon a) where Mon a <> Mon b = Mon (a ++ b) |
| 11:26:50 | <yahb> | dminuoso: ; <interactive>:55:27: error: parse error on input `where' |
| 11:26:54 | <dminuoso> | % instance Semigroup (Mon a) where Mon a <> Mon b = Mon (a ++ b) |
| 11:26:54 | <yahb> | dminuoso: |
| 11:27:00 | <dminuoso> | % instance Monoid (Mon a) where mempty = Mon []; |
| 11:27:00 | <yahb> | dminuoso: |
| 11:27:30 | <dminuoso> | Mmm not quite |
| 11:29:29 | <dminuoso> | ldlework: Anyway, at the end the key observation is: You can simply take a list of anything and make a minimal monoid with that. It adds monoidal structure, and nothing else. |
| 11:29:54 | <dminuoso> | We dont even specify what `a ++ b` even means |
| 11:32:37 | <hpc> | "We dont even specify what `a ++ b` even means" - leading with this would help a lot with future explanations |
| 11:34:03 | → | cheater joins (~Username@user/cheater) |
| 11:36:07 | → | gehmehgeh joins (~user@user/gehmehgeh) |
| 11:38:32 | <carbolymer> | are async exceptions masked in "last" computation in `Control.Exception.bracket` ? |
| 11:40:38 | <dminuoso> | carbolymer: Look at the implementation |
| 11:41:40 | <carbolymer> | dminuoso: I'm looking and I feel a bit sick today and I'm not sure if it is: |
| 11:41:40 | <carbolymer> | >restore ((thing a) `onException` after a) |
| 11:41:40 | <carbolymer> | or |
| 11:41:40 | <carbolymer> | >(restore (thing a)) `onException` after a |
| 11:42:10 | <dminuoso> | https://hackage.haskell.org/package/base-4.15.0.0/docs/src/Control-Exception-Base.html#bracket |
| 11:42:15 | <dminuoso> | r <- restore (thing a) `onException` after a |
| 11:42:28 | <carbolymer> | what's the priority of operations? |
| 11:42:48 | <carbolymer> | restore then onException? |
| 11:43:05 | <dminuoso> | Not sure what you mean by priority |
| 11:43:28 | <carbolymer> | which function is invoked last |
| 11:43:47 | <dminuoso> | Why is the "order" relevant here? |
| 11:43:57 | <hpc> | you mean fixity? |
| 11:44:00 | <carbolymer> | yes |
| 11:44:16 | <carbolymer> | dminuoso: because it answers the question if exceptions are masked in `after` |
| 11:44:27 | <dminuoso> | Ah you're looking for how this is parsed. |
| 11:44:29 | → | geekosaur joins (~geekosaur@xmonad/geekosaur) |
| 11:44:39 | <dminuoso> | (restore (thing a)) `onException` after a |
| 11:44:40 | <hpc> | prefix binds tighter than infix, so f x `op` g y is always (f x) `op` (g y) |
| 11:44:45 | <carbolymer> | dminuoso: thank you |
| 11:44:52 | <carbolymer> | hpc: thx |
| 11:44:57 | <carbolymer> | coffee does not work today |
| 11:45:01 | <shapr> | not YET |
| 11:45:08 | shapr | drinks much more coffee |
| 11:45:24 | <shapr> | violence is like coffee |
| 11:45:31 | <shapr> | neither of them type check |
| 11:45:38 | <hpc> | english breakfast tea is the superior wakeup juice :D |
| 11:46:06 | <shapr> | I choose four cups of death wish cold brew. |
| 11:46:23 | <dminuoso> | carbolymer: Note, that `restore` does not unmask exceptions, it just restores the previous exception mask before `mask` |
| 11:46:31 | <dminuoso> | Just adding that side note, in case you're using `bracket` in strange places |
| 11:47:21 | × | bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Ping timeout: 276 seconds) |
| 11:48:44 | <ldlework> | check this out https://i.imgur.com/HkcUQo3.png |
| 11:48:50 | <carbolymer> | dminuoso: my team is balls deep in a strange issue, "/dev/random: hClose: does not exist (No such file or directory)" - comes from warp-tls, and it freezes processing threads (some resource contention?), and we have no idea why, also we're using ancient linux kernel 3.10 |
| 11:49:11 | <carbolymer> | dminuoso: also profiling makes this bug irreproducible... |
| 11:49:26 | → | bitdex joins (~bitdex@gateway/tor-sasl/bitdex) |
| 11:49:28 | <carbolymer> | dminuoso: so yeah, we're probably onto some masking weirdness |
| 11:50:01 | × | __monty__ quits (~toonn@user/toonn) (Quit: Kernel woes : s) |
| 11:50:10 | <carbolymer> | ldlework: plantuml? |
| 11:51:03 | <Cajun> | Idlework: seeing UML diagrams for haskell is weeeeird, ive only seen those for lenses! really cool though, it would be interesting to have a really big one of these automatically generated for a given project |
| 11:51:40 | <ldlework> | carbolymer: yep |
| 11:51:50 | <carbolymer> | ldlework: written by hand or generated? |
| 11:52:00 | × | tromp quits (~textual@dhcp-077-249-230-040.chello.nl) (Quit: My iMac has gone to sleep. ZZZzzz…) |
| 11:52:06 | <ldlework> | carbolymer: written by hand because many typeclasses don't have the proper relationships in code |
| 11:52:44 | <ldlework> | awpr is going to help flesh it out, I'm just working out the plantuml conventions |
| 11:52:49 | <ldlework> | i mean, anyone can help |
| 11:52:59 | <Cajun> | although some parts are inconsistent with the parenthesis and tuples. Foldable as the tuple as `(,) a` and Monad as `((,) a)` |
| 11:53:04 | <ldlework> | I just fixed that |
| 11:53:08 | <Cajun> | :) |
| 11:53:19 | <ldlework> | https://i.imgur.com/eplRSKd.png |
| 11:53:48 | → | viluon joins (uid453725@id-453725.helmsley.irccloud.com) |
| 11:53:54 | <Cajun> | far right of Functor has a weird > on it |
| 11:54:50 | <ldlework> | nice |
| 11:55:27 | <ldlework> | https://i.imgur.com/Ce1zOGK.png |
| 11:55:58 | <ldlework> | oop missing a comma, guh |
| 11:56:18 | <ldlework> | Anyway, I eventually want to see how Reader and other typeclasses fit in here |
| 11:58:26 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 11:58:39 | → | juhp joins (~juhp@128.106.188.220) |
| 12:00:47 | × | jonathanx quits (~jonathan@dyn-8-sc.cdg.chalmers.se) (Remote host closed the connection) |
| 12:01:03 | → | jonathanx joins (~jonathan@dyn-8-sc.cdg.chalmers.se) |
| 12:06:31 | → | lavaman joins (~lavaman@98.38.249.169) |
| 12:10:07 | <ldlework> | If anyone wants to help add more typeclasses: https://github.com/dustinlacewell/haskell-typeclass-atlas |
| 12:10:50 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 252 seconds) |
| 12:11:27 | <ldlework> | Cajun, [exa], Cale ^ |
| 12:19:45 | → | tromp joins (~textual@dhcp-077-249-230-040.chello.nl) |
| 12:20:49 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 12:21:17 | dminuoso | is absolutely unsure what the relationship between Foldable and Ord is supposed to be |
| 12:22:41 | <ldlework> | dminuoso: One of Foldable's methods depends on Ord |
| 12:22:44 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 12:22:48 | <dminuoso> | Ermm.. |
| 12:22:49 | <ldlework> | maximum/minimum |
| 12:23:06 | <ldlework> | I'm new to haskell/category theory, so feel free to just chime in |
| 12:23:08 | <dminuoso> | So?> |
| 12:23:23 | <ldlework> | dminuoso: it's just meant to demonstrate such a relation |
| 12:23:25 | <dminuoso> | That doesnt give any relationship between Foldable and Ord, really |
| 12:23:31 | <dminuoso> | Any meaningful one, anyway |
| 12:24:03 | <dminuoso> | But Im not sure what this diagram is trying to convey or help with |
| 12:24:05 | <ldlework> | Like in another case you can easily see that you can use Foldable on Monoid objects |
| 12:24:33 | <ldlework> | dminuoso: that's fine, others have expressed it could be useful, and personally I'm just looking for a nice reference |
| 12:24:41 | <dminuoso> | What does "use Foldable on Monoid objects" even mean? |
| 12:25:06 | <ldlework> | If you have a Monoid you can call `fold` on it |
| 12:25:13 | <dminuoso> | No, you cant. |
| 12:25:22 | <dminuoso> | % :t fold |
| 12:25:22 | → | shriekingnoise joins (~shrieking@186.137.144.80) |
| 12:25:22 | <yahb> | dminuoso: (Foldable t, Monoid m) => t m -> m |
| 12:25:31 | <ldlework> | Well rather, if you have a Foldable holding a Monad |
| 12:25:38 | <ldlework> | Monoid* |
| 12:25:41 | <dminuoso> | `t m` is not "a monoid" |
| 12:25:53 | <dminuoso> | It's rather the foldable of a monoid can be mappended together. |
| 12:25:54 | <ldlework> | it's a foldable structuring a monoid |
| 12:25:57 | <dminuoso> | Sure. |
| 12:26:05 | <ldlework> | spoke too soon :) |
| 12:26:33 | <dminuoso> | Like I said, that relationship seems overly arbitrary |
| 12:26:49 | <dminuoso> | As Monoid is not part of Foldable's description |
| 12:26:56 | × | bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "") |
| 12:27:00 | <ldlework> | Sure, that's a different arrow :P |
| 12:27:05 | → | MQ-17J joins (~MQ-17J@8.21.10.6) |
| 12:27:09 | <dminuoso> | It's rather that `an arbitrary Monoid` is used in some methods. |
| 12:27:24 | <ldlework> | Foldable has a relation with Monoid that it doesn't have with, say, Applicative |
| 12:27:29 | <ldlework> | dminuoso: yes |
| 12:27:41 | × | benin036932301 quits (~benin@183.82.205.89) (Ping timeout: 264 seconds) |
| 12:28:35 | <dminuoso> | Thing is, it's not really part of Foldable's identity |
| 12:28:45 | <ldlework> | dminuoso: for context, awpr mentioned that there are some other relationships between typeclasses he wants to show, but as an ignorant neophyte, I don't know what they are - so in trying to accomplish my side of the goal of establishing some plantuml conventions, I just picked this arbitrary thing to test out alternative arrow styles on |
| 12:28:48 | <dminuoso> | Foldable could be stripped to just `foldr` or `foldl`, or maybe `toListOf` |
| 12:29:01 | <dminuoso> | So if you look at the *bare* minimum of a class, that's when you begin to realize its characteristics |
| 12:29:16 | <ldlework> | dminuoso: I tried to think of a good place / good way to show the "minimal" functions but didn't think of anything good yet |
| 12:29:28 | <dminuoso> | ldlework: you could perhaps make them bold? |
| 12:29:31 | <dminuoso> | If that works |
| 12:29:45 | <ldlework> | Yeah, I tried that, but it weakens the bolding in the title |
| 12:29:56 | <ldlework> | I could make the titles a bigger fontsize |
| 12:30:09 | <ldlework> | i wonder how underline looks |
| 12:30:20 | <dminuoso> | ldlework: Anyway. The thing is, the relationship to Monoid is sort of accidental - in the sense that there's a bunch of people that frequently use Monoid to fold something together. |
| 12:30:34 | <dminuoso> | but Foldable without `fold` and `foldMap` would be just as legit |
| 12:30:41 | <ldlework> | dminuoso: sure, we're not trying to show the minimal possible amount of information |
| 12:31:00 | <ldlework> | just trying to demonstrate some useful information among the major typeclasses |
| 12:31:02 | <ldlework> | btw |
| 12:31:04 | <dminuoso> | Well, what if there was a *function* using both Foldable and Comonad. Would that mean there had to be an arrow too? |
| 12:31:06 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 12:31:12 | <ldlework> | if you have any recommendations for other typeclasses you'd like to see on an atlas like this |
| 12:31:20 | <ldlework> | i'd be very happy to take those |
| 12:31:34 | × | tromp quits (~textual@dhcp-077-249-230-040.chello.nl) (Quit: My iMac has gone to sleep. ZZZzzz…) |
| 12:31:37 | <dminuoso> | ldlework: The key thing is, fold/foldMap being actual methods is rather a mechanism allowing for people to provide type specialized optimized versions. |
| 12:31:48 | <dminuoso> | But its in no way some demonstration of a relationship |
| 12:31:55 | <dminuoso> | Imagine if `fold` and `foldMap` were just top level functions |
| 12:32:00 | <dminuoso> | Would you still draw that arrow? |
| 12:32:05 | <ldlework> | dminuoso: it's just showing "there are some functions on this type, you can use with that type" |
| 12:32:07 | <ldlework> | nothing more |
| 12:32:17 | <ldlework> | so you can look at a glance, without inspecting all the functions first |
| 12:32:27 | <dminuoso> | Sure. Would you draw the arrows if `fold/foldMap` were regular functions? |
| 12:32:37 | <ldlework> | maybe? |
| 12:32:47 | <ldlework> | it's not meant to reflect the platonic definition of the thing |
| 12:32:51 | <dminuoso> | So do you intend to scrape the entirety of hackage to build that model? |
| 12:33:02 | <ldlework> | no, as it says "subset" |
| 12:33:23 | → | pbrisbin joins (~patrick@pool-173-49-147-250.phlapa.fios.verizon.net) |
| 12:33:46 | <ldlework> | a difficulty with communicating the minimal function set, is that some of them are defined as OR operators |
| 12:33:59 | <ldlework> | like for Eq, {-# MINIMAL (==) | (/=) #-} |
| 12:35:57 | <ldlework> | Could just have a section above the example instances I guess |
| 12:36:05 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 264 seconds) |
| 12:37:11 | → | tromp joins (~textual@dhcp-077-249-230-040.chello.nl) |
| 12:37:40 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 12:37:43 | → | slowButPresent joins (~slowButPr@user/slowbutpresent) |
| 12:46:27 | → | ub joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 12:47:31 | → | doyougnu joins (~user@c-73-25-202-122.hsd1.or.comcast.net) |
| 12:49:23 | <ldlework> | Added the required functions https://raw.githubusercontent.com/dustinlacewell/haskell-typeclass-atlas/master/atlas.png |
| 12:50:03 | → | wonko joins (~wjc@62.115.229.50) |
| 12:51:05 | × | ub quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Ping timeout: 264 seconds) |
| 12:52:15 | × | jonathanx quits (~jonathan@dyn-8-sc.cdg.chalmers.se) (Remote host closed the connection) |
| 12:52:32 | → | jonathanx joins (~jonathan@dyn-8-sc.cdg.chalmers.se) |
| 12:53:03 | × | tromp quits (~textual@dhcp-077-249-230-040.chello.nl) (Quit: My iMac has gone to sleep. ZZZzzz…) |
| 12:53:46 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 12:53:59 | → | juhp joins (~juhp@128.106.188.220) |
| 12:56:47 | → | waleee joins (~waleee@2001:9b0:216:8200:d457:9189:7843:1dbd) |
| 13:04:06 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 13:04:22 | → | juhp joins (~juhp@128.106.188.220) |
| 13:04:44 | × | MQ-17J quits (~MQ-17J@8.21.10.6) (Ping timeout: 252 seconds) |
| 13:04:55 | <DigitalKiwi> | ldlework: are you using haskell out of anger or joy (glad to see you here anyway) |
| 13:05:03 | → | MQ-17J joins (~MQ-17J@8.21.10.6) |
| 13:05:09 | <ldlework> | joy |
| 13:05:16 | <ldlework> | i'm pretty confused overall, but i like MLs |
| 13:05:23 | <DigitalKiwi> | \o/ |
| 13:06:07 | <ldlework> | it's going to take me a really long to meaningfully absorb the principled mathematical stuff behind the typeclasses, but i am working at it |
| 13:07:13 | <ldlework> | long time* |
| 13:07:39 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 13:07:41 | <DigitalKiwi> | have you https://github.com/hmemcpy/milewski-ctfp-pdf |
| 13:08:04 | <ldlework> | no, still working through HFFP |
| 13:08:58 | → | spruit11 joins (~quassel@2a02:a467:ccd6:1:40b2:87e8:dd1:e5c1) |
| 13:09:21 | <ldlework> | thanks for the link though |
| 13:09:27 | <DigitalKiwi> | do you mean HPFP or a different one i don't know |
| 13:09:35 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 13:09:48 | <DigitalKiwi> | oh a different one |
| 13:10:11 | <DigitalKiwi> | or nvrm i have no idea lol |
| 13:10:47 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 13:10:47 | <ldlework> | DigitalKiwi: Haskell From First Principles |
| 13:10:51 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 13:11:47 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Ping timeout: 246 seconds) |
| 13:12:08 | → | machinedgod joins (~machinedg@135-23-192-217.cpe.pppoe.ca) |
| 13:14:18 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 13:14:29 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 13:14:37 | <DigitalKiwi> | lol i think we're talking about the same book but i read it as Haskell Programming from First Principles |
| 13:14:42 | → | juhp joins (~juhp@128.106.188.220) |
| 13:15:38 | <viluon> | hi, a couple minutes ago I sent an email to haskell-cafe titled "Optimising ReadP," if anyone wants to discuss it here, I'd be happy to |
| 13:15:49 | → | tromp joins (~textual@dhcp-077-249-230-040.chello.nl) |
| 13:17:38 | <kuribas> | can't wait for merijn to comment :) |
| 13:19:28 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 13:19:48 | <merijn> | My main comment would be "don't bother, just nuke it from orbit" >.> |
| 13:20:03 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 13:22:19 | → | chris joins (~chris@81.96.113.213) |
| 13:22:24 | chris | is now known as Guest3409 |
| 13:22:53 | × | spruit11 quits (~quassel@2a02:a467:ccd6:1:40b2:87e8:dd1:e5c1) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.) |
| 13:25:05 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 13:29:49 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 13:30:04 | → | juhp joins (~juhp@128.106.188.220) |
| 13:35:10 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 13:35:20 | <merijn> | viluon: Basically, ReadP having garbage performance is well known and it's less effort to just port your parser to another parser combinator library then it is to optimise ReadP |
| 13:35:24 | → | juhp joins (~juhp@128.106.188.220) |
| 13:36:06 | <viluon> | merijn: thanks, would you happen to know why is the performance so poor? |
| 13:36:09 | <geekosaur> | ReadP's only saving grace is that it can easily be implemented using only features from base, so it can be used to implement Read instances |
| 13:36:17 | <merijn> | viluon: Because ReadP supports ambiguous grammars |
| 13:36:30 | <merijn> | viluon: So it it keeps all possible parse traces around |
| 13:36:36 | <viluon> | ah |
| 13:36:43 | <merijn> | viluon: It also operates on String which is a terrible datatype for parsing |
| 13:36:54 | <viluon> | yes, `String` is awful |
| 13:36:58 | <viluon> | could you recommend an alternative? |
| 13:37:22 | <merijn> | viluon: megaparsec is the most feature complete one. Attoparsec is more minimal in case you don't care about error message quality. |
| 13:37:36 | <merijn> | viluon: Parsec if you need to support ridiculously old code |
| 13:37:42 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 13:37:48 | <viluon> | is there something even smaller than attoparsec? |
| 13:37:51 | <merijn> | But in general megaparsec is the safe bet. Which also lets you parse Text directly |
| 13:37:56 | <merijn> | viluon: Not really |
| 13:38:00 | <dminuoso> | attoparsec already is fairly small |
| 13:38:17 | <dminuoso> | It's dependency footprint is as limited as it can reasonably get |
| 13:38:57 | <merijn> | But yeah, ReadP is mostly around for stuff like Read (which also has garbage performance >.>) |
| 13:40:44 | <merijn> | viluon: Compare your numbers with stuff like: https://markkarpov.com/post/megaparsec-more-speed-more-power.html |
| 13:42:03 | <[itchyjunk]> | wait, i confused myself. haskell functions can only ever take one argument. but i thought we said integers a functions that take no parameters? |
| 13:42:20 | <dminuoso> | No, we never did. |
| 13:42:25 | <[itchyjunk]> | oh.. |
| 13:42:31 | <[itchyjunk]> | weren't integers functions? |
| 13:42:32 | <dminuoso> | And that statement is silly and nonsense. |
| 13:42:34 | <dminuoso> | No. |
| 13:42:46 | <dminuoso> | First, what do you mean by "integers" exactly? |
| 13:42:50 | <[itchyjunk]> | 1 |
| 13:42:55 | <dminuoso> | The expression 1? |
| 13:43:05 | <dminuoso> | So the expression 1 is a polymorphic value, it's not a function. |
| 13:43:10 | <dminuoso> | It's type is `Num a => a` |
| 13:43:37 | <[itchyjunk]> | hmmm |
| 13:44:10 | <dminuoso> | A function is one that maps values of its domain onto values onto its codomain. For instance, a function `f :: Int -> Char` maps every value of type Int to some value of type Char. |
| 13:44:16 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 13:44:16 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 13:44:16 | → | wroathe joins (~wroathe@user/wroathe) |
| 13:44:21 | <dminuoso> | So you see, the phrase "function that takes no parameters" is nonsensical |
| 13:44:41 | <shapr> | has anyone used dataflower at all? |
| 13:45:07 | <shapr> | I see many opportunities for timely dataflow in my daily work, but probably would only try such a framework in Haskell |
| 13:45:22 | <merijn> | [itchyjunk]: See also: http://conal.net/blog/posts/everything-is-a-function-in-haskell |
| 13:46:15 | <dminuoso> | merijn is a manually driven car, just without any of the metal or plastic stuff. |
| 13:46:32 | × | nvmd quits (~nvmd@user/nvmd) (Ping timeout: 252 seconds) |
| 13:46:37 | → | bontaq joins (~user@ool-45779fe5.dyn.optonline.net) |
| 13:48:12 | → | nvmd joins (~nvmd@user/nvmd) |
| 13:49:12 | → | jokleinn joins (~jokleinn@user/jokleinn) |
| 13:49:27 | <[itchyjunk]> | merijn, the "7" being sugar notation for ()->7 being mentioned in that post, isn't that functional notation? |
| 13:49:43 | × | zaquest quits (~notzaques@5.128.210.178) (Remote host closed the connection) |
| 13:50:46 | <[itchyjunk]> | i'll read through this first |
| 13:51:25 | <merijn> | [itchyjunk]: The post mentions that's nonsense too :p |
| 13:51:32 | <shapr> | I have complaints about haddock, but hoogle still one of the most amazing things in Haskell |
| 13:52:53 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 264 seconds) |
| 13:52:53 | <[itchyjunk]> | I'll have to remembe who i discussed it with.. |
| 13:53:02 | <[itchyjunk]> | i thought for sure i talked to someone about this .. |
| 13:53:33 | → | zaquest joins (~notzaques@5.128.210.178) |
| 13:55:34 | × | tromp quits (~textual@dhcp-077-249-230-040.chello.nl) (Quit: My iMac has gone to sleep. ZZZzzz…) |
| 13:56:29 | × | jstolarek quits (~jstolarek@erx128.neoplus.adsl.tpnet.pl) (Ping timeout: 264 seconds) |
| 13:59:11 | × | MQ-17J quits (~MQ-17J@8.21.10.6) (Ping timeout: 252 seconds) |
| 13:59:42 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 14:01:38 | <[itchyjunk]> | This reminds me of something else i was thinking off and getting really confused about |
| 14:02:33 | <[itchyjunk]> | someone had told me scalars are just 1 dimentional matrices like [1] and it kinda made snese. but matrix multiplication and scalar multiplication are different beasts.. |
| 14:02:40 | <[itchyjunk]> | maybe i got bamboozeled there too |
| 14:04:31 | × | nfd quits (~nfd@user/nfd) (Ping timeout: 265 seconds) |
| 14:04:49 | <opqdonut> | but matrix multiplication for matrices of size 1x1 works exactly like scalar multiplication? |
| 14:05:20 | → | Izem joins (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 14:06:13 | × | alx741 quits (~alx741@186.178.109.159) (Ping timeout: 252 seconds) |
| 14:06:23 | <opqdonut> | even though matrix multiplication isn't commutative _in general_ there are classes of matrices where it is commutative. 1x1 matrices are one example. diagonal matrices are another |
| 14:06:33 | <[itchyjunk]> | yes but i can take a scalar and multiply it to any sized matrix |
| 14:06:41 | <[itchyjunk]> | but if 1 is [1], this stops working |
| 14:06:56 | <opqdonut> | yeah scaling is different |
| 14:07:24 | <opqdonut> | scaling shouldn't use the same symbol as multiplication, it doesn't even have the same type! |
| 14:07:59 | <opqdonut> | and e.g. vector spaces have scaling but might not have multiplication |
| 14:10:08 | × | nshepperd2 quits (~nshepperd@li364-218.members.linode.com) (Quit: Ping timeout (120 seconds)) |
| 14:10:22 | → | nshepperd2 joins (~nshepperd@li364-218.members.linode.com) |
| 14:10:53 | × | Guest3409 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 14:11:11 | → | SquidDev1 joins (~SquidDev@autoclave.squiddev.cc) |
| 14:11:49 | → | Nahra` joins (~user@static.161.95.99.88.clients.your-server.de) |
| 14:12:16 | × | ouroboros quits (~ouroboros@user/ouroboros) (Ping timeout: 252 seconds) |
| 14:12:18 | → | Philonous_ joins (~Philonous@user/philonous) |
| 14:12:19 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 14:12:49 | × | Nahra quits (~user@static.161.95.99.88.clients.your-server.de) (Ping timeout: 252 seconds) |
| 14:12:49 | × | Philonous quits (~Philonous@user/philonous) (Ping timeout: 252 seconds) |
| 14:12:49 | × | sweater quits (~sweater@206.81.18.26) (Ping timeout: 252 seconds) |
| 14:13:20 | → | joeyh_ joins (~joeyh@kitenet.net) |
| 14:13:22 | × | jlamothe quits (~jlamothe@104.158.48.100) (Ping timeout: 252 seconds) |
| 14:13:22 | × | jonatan quits (~nate@h85-8-60-194.cust.a3fiber.se) (Ping timeout: 252 seconds) |
| 14:13:22 | × | clever quits (~clever@99.192.114.98) (Ping timeout: 252 seconds) |
| 14:13:22 | × | SquidDev quits (~SquidDev@autoclave.squiddev.cc) (Ping timeout: 252 seconds) |
| 14:13:22 | × | joeyh quits (~joeyh@kitenet.net) (Ping timeout: 252 seconds) |
| 14:13:22 | SquidDev1 | is now known as SquidDev |
| 14:13:54 | → | jonatan joins (~nate@h85-8-60-194.cust.a3fiber.se) |
| 14:14:14 | → | jlamothe joins (~jlamothe@104.158.48.100) |
| 14:14:30 | → | sweater joins (~sweater@206.81.18.26) |
| 14:14:46 | × | hendursa1 quits (~weechat@user/hendursaga) (Quit: hendursa1) |
| 14:15:10 | → | hendursaga joins (~weechat@user/hendursaga) |
| 14:17:59 | → | chris joins (~chris@81.96.113.213) |
| 14:18:03 | chris | is now known as Guest250 |
| 14:18:27 | → | ouroboros joins (~ouroboros@user/ouroboros) |
| 14:18:48 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 14:19:07 | → | alx741 joins (~alx741@186.178.109.225) |
| 14:19:40 | → | clever joins (~clever@99.192.114.98) |
| 14:20:22 | <viluon> | merijn: I switched to attoparsec, getting the total runtime from 100 ms to 80. 21% of allocations happen in `decimal.step` (from `Data.Attoparsec.Text`), again a generic definition I cannot specialise as it lacks an `INLINE(ABLE)` pragma |
| 14:20:51 | <merijn> | Which optimisation level? |
| 14:21:05 | × | acidjnk quits (~acidjnk@p200300d0c703cb44319f4c33bc64626e.dip0.t-ipconnect.de) (Ping timeout: 246 seconds) |
| 14:21:26 | × | Vajb quits (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) (Read error: Connection reset by peer) |
| 14:21:34 | <merijn> | And why do you think 1) inlining will avoid allocations and 2) the allocations need to be avoided to speed things up? |
| 14:22:53 | × | Guest250 quits (~chris@81.96.113.213) (Ping timeout: 264 seconds) |
| 14:23:24 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 14:24:56 | × | waleee quits (~waleee@2001:9b0:216:8200:d457:9189:7843:1dbd) (Ping timeout: 246 seconds) |
| 14:24:59 | → | Vajb joins (~Vajb@2001:999:63:cb56:7735:f6b9:cd89:d4c7) |
| 14:26:07 | → | chris joins (~chris@81.96.113.213) |
| 14:26:11 | chris | is now known as Guest9962 |
| 14:27:09 | → | waleee joins (~waleee@h-98-128-228-119.NA.cust.bahnhof.se) |
| 14:27:21 | → | maroloccio joins (~marolocci@93-142-92-177.adsl.net.t-com.hr) |
| 14:27:52 | <lortabac> | merijn: inlining in GHC includes beta reduction, so it can save allocations in some cases |
| 14:28:18 | × | n3t quits (n3t@s45.mydevil.net) (Read error: Connection reset by peer) |
| 14:28:26 | × | shapr quits (~user@pool-100-36-247-68.washdc.fios.verizon.net) (Ping timeout: 246 seconds) |
| 14:28:35 | <viluon> | merijn: oxygen (`-O2`). With `ReadP` (or rather the `Lex` utilities), specialising them to `Int` helped. Granted, `decimal.step` is only 8.9% of total time, bigger cost-centres are `>>=.\.succ'` (35.9% time, 30.5% alloc), `>>=.\` (16% time, 17.5% alloc), `fmap.\` (11.0% time, 9.6% alloc), and `fmap.\.succ'` (9.3% time, 11.1% alloc). These are all from `Data.Attoparsec.Internal.Types`. |
| 14:28:36 | <viluon> | I don't have a good model of what optimisations could help here, getting one is part of the motivation for this experiment. I'm surprised that the potentially very powerful specialisation and inlining directives are so limited in practical uses. |
| 14:29:23 | → | n3t joins (n3t@s45.mydevil.net) |
| 14:30:22 | <viluon> | in any case, I still think the parser creates a lot of garbage. I'd at least like to find out what that garbage is; I'll try heap profiling next. |
| 14:30:41 | × | lbseale quits (~lbseale@user/ep1ctetus) (Ping timeout: 264 seconds) |
| 14:31:08 | <merijn> | What's the problem with lots of garbage, though? |
| 14:31:11 | <merijn> | Garbage is cheap |
| 14:31:29 | <merijn> | So is allocation |
| 14:31:34 | <merijn> | It's non-garbage you gotta worry about |
| 14:31:41 | × | rond_ quits (~rond_@2a02:a31a:a23c:f480:2fd7:e087:5546:a438) (Quit: Client closed) |
| 14:32:35 | <viluon> | I use `IntMap (Set Int)` to represent a directed graph |
| 14:33:24 | <merijn> | Also, on what sorta input? You mention 80ms parse, why is that a problem? |
| 14:33:35 | <viluon> | if the parser first builds the entirety of it as a `[(Int, Int)]` and then converts to the map with a `foldl'`, I wasted a lot of time allocating garbage and then traversing a cache-unfriendly data structure |
| 14:33:49 | <merijn> | Like, there's a lot of missing information about what you're trying to optimise, with what goal |
| 14:34:16 | <merijn> | viluon: Allocating garbage is cheap, though |
| 14:34:34 | <viluon> | no it's not |
| 14:34:39 | <merijn> | viluon: You gotta abandon any notion about cost of allocation you have from C/Rust |
| 14:34:44 | <viluon> | the Rust implementation finishes this test case under 10ms |
| 14:34:51 | <merijn> | GHC's alloation is *really* cheap |
| 14:35:17 | <merijn> | The fact that the attoparsec parser is slower doesn't necessarily mean it's the allocation that's causing that |
| 14:35:35 | <merijn> | Boxing alone will cost you a bunch of performance compared to Rust |
| 14:35:53 | <viluon> | i don't really mind if it's allocation or some other thing, I just want to speed it up |
| 14:36:02 | <viluon> | although I am interested in laziness pitfalls |
| 14:36:21 | <merijn> | viluon: Well, you haven't pasted any code nor profiling output, so that's gonna limit how much useful feedback you get |
| 14:36:58 | <viluon> | it's a topological sorting implementation that spends 80+% of the time loading input |
| 14:37:02 | → | lbseale joins (~lbseale@user/ep1ctetus) |
| 14:37:40 | <merijn> | That's nice. But that's entirely useless information for getting feedback on how you might speed things up |
| 14:37:52 | → | Sgeo joins (~Sgeo@user/sgeo) |
| 14:38:12 | <viluon> | alright, I'll share the code |
| 14:38:29 | <merijn> | All I've seen is some random function names and allocation/time percentages. I mean, what do you expect people to comment on that? |
| 14:38:51 | → | flouflou joins (~flouflou@modemcable032.110-177-173.mc.videotron.ca) |
| 14:38:57 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 14:39:12 | <merijn> | If you wanna be fast, you probably wanna use a Vector based datatype that's filled incrementally from attoparsec, rather than IntMap (Set Int) |
| 14:39:15 | <viluon> | not random: they come from a supposedly widely used library |
| 14:39:48 | <viluon> | "These are all from `Data.Attoparsec.Internal.Types`" |
| 14:39:50 | <merijn> | viluon: Allocation percentage of "fmap" is meaningless without code |
| 14:40:04 | × | lbseale quits (~lbseale@user/ep1ctetus) (Remote host closed the connection) |
| 14:40:29 | → | lbseale joins (~lbseale@user/ep1ctetus) |
| 14:40:42 | <viluon> | here's the code: https://paste.tomsmeding.com/4G0bpLx7 |
| 14:41:23 | <viluon> | I don't want to sound ungrateful, I really appreciate you taking the time to answer my questions! |
| 14:42:50 | <merijn> | viluon: Inst has boxed ints, which you probably don't want, that build in parse' also seems a candidate for a lot of blow up |
| 14:43:14 | <merijn> | viluon: Can't you replace the Set with an (optionally) sorted unboxed Vector? |
| 14:43:44 | <viluon> | it is inlined and uses a strict fold, `parse'` doesn't show up in top cost centres |
| 14:44:33 | <merijn> | viluon: My point is that IntMap + Set is gonna be pretty horrible for accessing a static graph |
| 14:44:49 | <merijn> | I'm pretty sure the Rust version doesn't do that and uses an array based representation like CSR |
| 14:45:21 | <merijn> | And there's no real reason you couldn't use the same thing in Haskell |
| 14:45:28 | <viluon> | sure, but does that matter? |
| 14:45:45 | <viluon> | these are the top cost centres https://paste.tomsmeding.com/26S86CNo |
| 14:46:57 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 14:47:02 | <merijn> | viluon: btw, note that your use of strict state is mostly useless as all the elements in the tuple are still lazy |
| 14:47:52 | <viluon> | tbf, the test case I'm running this on may be one where the interesting portion of the digraph lies in a small connected component, so time is spent when processing input but most of it is ignored by the DFS |
| 14:48:55 | → | favonia joins (~favonia@user/favonia) |
| 14:48:56 | × | Vajb quits (~Vajb@2001:999:63:cb56:7735:f6b9:cd89:d4c7) (Read error: Connection reset by peer) |
| 14:49:27 | <merijn> | viluon: What's the output of running with: +RTS -sstderr |
| 14:49:47 | × | jacks2 quits (~bc8165b6@217.29.117.252) (Quit: http://www.okay.uz/ (Session timeout)) |
| 14:49:48 | → | Vajb joins (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) |
| 14:50:00 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 14:50:49 | × | Guest9962 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 14:52:51 | <viluon> | here's the profiling result for a more comprehensive test case: https://paste.tomsmeding.com/RTMOuOID Rust 26.6 ms ± 1.7 ms, Haskell 1.058 s ± 0.054 s. Of course it's far from a fair comparison as both implementations use different approaches, but as the cost centres show, the majority of time is again spent in the parser |
| 14:53:12 | <viluon> | I should profile the Rust implementation too I think |
| 14:54:08 | <merijn> | Also, are you comparing apples-to-apples? Attoparsec Text does full unicode |
| 14:54:24 | <viluon> | apples-to-apples? Definitely not |
| 14:54:26 | <merijn> | If the Rust one is only doing ascii, you might wanna compare with the ByteString one |
| 14:54:47 | <merijn> | Because a full unicode parser is obviously gonna be slower than a narrow ascii only one |
| 14:55:26 | <viluon> | I don't care too much really, the Rust implementation isn't mine. A friend wrote it, then I wrote the Haskell one, and I'm embarrassed that mine is orders of magnitude slower |
| 14:56:00 | <viluon> | but I also want to take this opportunity to investigate how often does laziness get in the way of productivity and get an idea of where could GHC improve its optimisation efforts |
| 14:57:05 | <viluon> | here's the RTS report as you requested. Again, thanks for all your feedback, questions and suggestions! https://paste.tomsmeding.com/sie584Ts |
| 14:57:32 | × | Izem quits (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Quit: Izem) |
| 14:57:37 | <merijn> | Who says the problem here is laziness, though? Or allocation, or inlining as you implied at the start |
| 14:57:40 | <merijn> | ok |
| 14:57:44 | <merijn> | So, that is a clear sign |
| 14:57:48 | → | Izem joins (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 14:57:55 | <merijn> | Productivity 57% <- this is garbage |
| 14:58:07 | → | Guest6237 joins (~chris@81.96.113.213) |
| 14:58:11 | → | hnOsmium0001 joins (uid453710@id-453710.hampstead.irccloud.com) |
| 14:58:17 | → | ysh joins (sid6017@id-6017.ilkley.irccloud.com) |
| 14:58:21 | <merijn> | Productivity should be 80-90%. So that means you're keeping data alive too long |
| 14:59:08 | <viluon> | > Who says the problem here is laziness, though? Or allocation, or inlining as you implied at the start |
| 14:59:08 | <viluon> | I didn't, I'm trying to find out |
| 14:59:10 | <lambdabot> | <hint>:1:38: error: parse error on input ‘,’ |
| 14:59:17 | <viluon> | whoops, sorry lambdabot |
| 15:00:04 | <merijn> | viluon: anyway, so currently you're parsing the entire input into a list of Inst, then traversing the list with your solver |
| 15:00:34 | <merijn> | That's a lot of data to be live, which would explain the garbage productivity |
| 15:01:11 | <merijn> | So I would see what happens if you run the solver immediately when you finish parsing one Inst, so you only have 1 Inst at a time |
| 15:01:22 | <viluon> | the list of problem instances (hence `Inst`) isn't longer than 100 elements |
| 15:01:24 | <merijn> | i.e. parse Inst, solve, continue |
| 15:01:27 | × | jonathanx quits (~jonathan@dyn-8-sc.cdg.chalmers.se) (Remote host closed the connection) |
| 15:01:47 | <merijn> | viluon: But each of those elements has an "IntMap (Set Int)" they keep alive |
| 15:01:53 | <viluon> | yes |
| 15:02:14 | × | [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Read error: Connection reset by peer) |
| 15:02:23 | × | Guest6237 quits (~chris@81.96.113.213) (Ping timeout: 246 seconds) |
| 15:02:26 | <merijn> | viluon: In GHC GC cost is proportional to amount of live data |
| 15:02:54 | → | ikex1 joins (~ash@user/ikex) |
| 15:02:57 | <merijn> | So keeping those alive a long time increases the GC cost. If you can turn them into garbage asap (by solving immediately) GC cost goes down and productivity goes up |
| 15:03:42 | <merijn> | Currently 40% of your runtime is running the GC |
| 15:03:58 | × | ikex quits (ash@user/ikex) (Ping timeout: 252 seconds) |
| 15:03:58 | ikex1 | is now known as ikex |
| 15:04:08 | <merijn> | So you wanna improve the rate at which you turn things into garbage |
| 15:04:17 | <viluon> | hmm, concerning |
| 15:04:34 | <viluon> | "So I would see what happens if you run the solver immediately when you finish parsing one Inst, so you only have 1 Inst at a time" <- is there a way to do that without modifying the code? |
| 15:05:21 | <viluon> | is there anything in my implementation that requires GHC to produce code that first parses everything and then processes one-by-one? |
| 15:05:24 | <merijn> | viluon: On line 38, instead of returning the Inst, just call your solve function there? |
| 15:05:35 | <merijn> | viluon: Yes |
| 15:06:13 | <merijn> | viluon: Your "parse" has to consume the entire input and turn it into a list to know if the parse succeeds |
| 15:06:57 | <merijn> | viluon: Alternatively you'd want one of the streaming libraries to interleave parsing Inst instance and solving them, which would also enforce the "1 element at a time" |
| 15:07:15 | → | x28girl joins (~x28girl@user/x28girl) |
| 15:08:02 | → | shapr joins (~user@pool-100-36-247-68.washdc.fios.verizon.net) |
| 15:08:03 | <merijn> | viluon: For cases like this where you're mostly parsing a stream of inputs and processing them, streaming libraries like conduit/pipes/etc. help interleave the IO/parsing and processing |
| 15:08:09 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 15:08:51 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 15:09:17 | <merijn> | (of course, that's a bit more boilerplate to set up) |
| 15:09:31 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 15:09:38 | <viluon> | I changed the definition of `solve` to `solve = fromMaybe [] . maybeResult . Attoparsec.parse (fmap solve' <$> parse) <$> Text.getContents` |
| 15:10:15 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 15:10:19 | <merijn> | Not sure that's gonna help with the double fmap, but it might |
| 15:10:49 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 15:11:38 | <viluon> | it did not |
| 15:12:02 | <viluon> | but now there's no reason to parse everything at once, is there? |
| 15:12:13 | <monochrom> | Absolutely no reason. |
| 15:14:29 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Ping timeout: 264 seconds) |
| 15:15:00 | <monochrom> | Lately I wrote my own "parser" monad that restores laziness by sacrificing error checking. The use case is that there won't be parse errors anyway. |
| 15:15:17 | × | maroloccio quits (~marolocci@93-142-92-177.adsl.net.t-com.hr) (Quit: WeeChat 3.0) |
| 15:15:21 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 15:15:55 | <monochrom> | Therefore one point is that "String -> []/Maybe (String, a)" is reduced to "String -> (String, a)". (This is not compulsory.) |
| 15:16:00 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 15:16:03 | × | oxide quits (~lambda@user/oxide) (Ping timeout: 265 seconds) |
| 15:17:12 | → | ub joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 15:17:42 | → | oxide joins (~lambda@user/oxide) |
| 15:18:04 | <monochrom> | The second point is I define "later (P f) = P (\s -> case f s of ~(s2, a) -> (s2, a))" |
| 15:18:33 | <monochrom> | Note how it increases laziness at the right place. |
| 15:19:01 | → | Guest70 joins (~Guest70@p200300f7770a55e9b9601923eb36d679.dip0.t-ipconnect.de) |
| 15:19:09 | <monochrom> | And it is analogous to unsafeInterleaveIO. |
| 15:19:25 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Remote host closed the connection) |
| 15:20:27 | <monochrom> | So now I can have my own lazier version of replicateM. rep n p = do { x <- p; xs <- later (rep (n-1) p); pure (x:xs) } |
| 15:20:49 | <ldlework> | nerd |
| 15:21:08 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds) |
| 15:21:16 | <monochrom> | This will run x<-p, jump ahead to "pure (x:xs)", and delay running rep (n-1) p until you force xs. |
| 15:22:14 | × | ub quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Ping timeout: 252 seconds) |
| 15:22:17 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 15:22:26 | <monochrom> | Alternatively, you can decide to make this pervasive, and build the ~(s2, a) lazy pattern right in the definition of >>=. This is what Control.Monad.Trans.State.Lazy does. |
| 15:22:56 | <monochrom> | So every m>>=cb is effectively m>>=\a->later(cb a) |
| 15:23:15 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 15:24:13 | <viluon> | merijn: any other suggestions? I don't want to introduce a streaming library for something that should not have these performance issues in the first place and I don't like the idea of changing my input parser into a solver – I want reusable code, and I'd like it to perform well when I compose it with other code. Sadly the optimiser is a black box and its decisions are unknowable to me |
| 15:24:45 | → | chris joins (~chris@81.96.113.213) |
| 15:24:49 | chris | is now known as Guest8849 |
| 15:26:13 | <viluon> | oh wait, merijn is gone |
| 15:28:21 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 15:30:14 | × | lortabac quits (~lortabac@2a01:e0a:541:b8f0:4252:bf51:4908:8ea0) (Quit: WeeChat 2.8) |
| 15:30:19 | → | mikoto-chan joins (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) |
| 15:34:12 | × | gehmehgeh quits (~user@user/gehmehgeh) (Ping timeout: 276 seconds) |
| 15:35:18 | → | gehmehgeh joins (~user@user/gehmehgeh) |
| 15:35:33 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:35:51 | <Izem> | How do you say `reads :: (Read a) => ReadS a` in English? reads has type ... |
| 15:35:53 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:36:39 | <monochrom> | ReadS a, but a has to be an instance of Read |
| 15:36:39 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:36:54 | <monochrom> | Frankly I wouldn't translate to English. |
| 15:36:59 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:37:03 | × | Guest70 quits (~Guest70@p200300f7770a55e9b9601923eb36d679.dip0.t-ipconnect.de) (Quit: Client closed) |
| 15:37:08 | × | cfricke quits (~cfricke@user/cfricke) (Quit: WeeChat 3.2.1) |
| 15:37:26 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:37:34 | <monochrom> | It is fair to ask how to work with that type, and how to write your own. |
| 15:37:46 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:37:51 | <monochrom> | "how to translate to English" is an XY problem. |
| 15:37:59 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:38:04 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 15:38:04 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 15:38:04 | → | wroathe joins (~wroathe@user/wroathe) |
| 15:38:18 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:38:18 | <monochrom> | If programming were better off in English, we would all be in a #cobol channel already. |
| 15:38:27 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:39:05 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:39:21 | <monochrom> | This is why I wrote http://www.vex.net/~trebla/haskell/prerequisite.xhtml |
| 15:40:01 | <monochrom> | Use your algebra skills, so you are free of the clumsiness of English when code gets real. |
| 15:41:12 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:41:30 | <monochrom> | English is not compositional. Programming languages are. This is not just Haskell. You can also have "daunting" types and terms in Java and C. |
| 15:41:32 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:42:03 | × | x28girl quits (~x28girl@user/x28girl) (Remote host closed the connection) |
| 15:42:47 | → | x28girl joins (~x28girl@user/x28girl) |
| 15:43:01 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds) |
| 15:43:05 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:43:25 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:43:33 | × | x28girl quits (~x28girl@user/x28girl) (Remote host closed the connection) |
| 15:44:05 | ← | jakalx parts (~jakalx@base.jakalx.net) (Error from remote client) |
| 15:45:27 | → | chronon joins (~chronon@user/chronon) |
| 15:45:33 | × | doyougnu quits (~user@c-73-25-202-122.hsd1.or.comcast.net) (Remote host closed the connection) |
| 15:45:50 | → | doyougnu joins (~user@c-73-25-202-122.hsd1.or.comcast.net) |
| 15:49:46 | <viluon> | is there a way to get a more detailed heap profile? the cost centres in the default `-hc` report just end with `...` |
| 15:49:56 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 15:50:10 | <viluon> | wb merijn |
| 15:50:50 | × | jokleinn quits (~jokleinn@user/jokleinn) (Ping timeout: 252 seconds) |
| 15:50:54 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:51:13 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:51:27 | → | jokleinn joins (~jokleinn@user/jokleinn) |
| 15:51:47 | × | xiongxin quits (~quassel@119.123.102.205) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.) |
| 15:51:48 | × | jpds quits (~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection) |
| 15:52:35 | × | qbt quits (~edun@user/edun) (Quit: Leaving) |
| 15:53:09 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 15:53:18 | → | jakalx joins (~jakalx@base.jakalx.net) |
| 15:53:28 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 15:54:32 | → | yinghua joins (~yinghua@2800:2121:1400:1db:705e:acf0:71e7:8a79) |
| 15:54:41 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 252 seconds) |
| 15:55:40 | × | mikoto-chan quits (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) (Ping timeout: 252 seconds) |
| 15:56:14 | → | mikoto-chan joins (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) |
| 15:56:45 | → | __monty__ joins (~toonn@user/toonn) |
| 15:58:32 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 16:03:50 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 16:04:29 | × | chele quits (~chele@user/chele) (Remote host closed the connection) |
| 16:05:14 | × | Guest8849 quits (~chris@81.96.113.213) (Remote host closed the connection) |
| 16:06:00 | × | pavonia quits (~user@user/siracusa) (Quit: Bye!) |
| 16:08:17 | → | lavaman joins (~lavaman@98.38.249.169) |
| 16:12:42 | → | chris joins (~chris@81.96.113.213) |
| 16:12:46 | chris | is now known as Guest2529 |
| 16:12:50 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 252 seconds) |
| 16:14:30 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 16:17:14 | × | Guest2529 quits (~chris@81.96.113.213) (Ping timeout: 252 seconds) |
| 16:17:19 | → | zebrag joins (~chris@user/zebrag) |
| 16:17:28 | → | tzh joins (~tzh@c-24-21-73-154.hsd1.or.comcast.net) |
| 16:19:07 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 16:28:42 | → | tommd joins (~tommd@75-164-130-101.ptld.qwest.net) |
| 16:31:02 | → | nfd joins (~nfd@user/nfd) |
| 16:31:15 | → | cfricke joins (~cfricke@user/cfricke) |
| 16:34:50 | × | nschoe quits (~quassel@178.251.84.79) (Ping timeout: 265 seconds) |
| 16:35:14 | → | nschoe joins (~quassel@178.251.84.79) |
| 16:36:42 | × | jokleinn quits (~jokleinn@user/jokleinn) (Quit: WeeChat 3.2) |
| 16:45:06 | → | rond_ joins (~rond_@2a02:a31a:a23c:f480:2fd7:e087:5546:a438) |
| 16:50:16 | → | bonizzi joins (~bonizzi@2804:14c:65d3:4689:d52e:1289:d36a:ed19) |
| 16:50:30 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 16:50:43 | → | juhp joins (~juhp@128.106.188.220) |
| 16:51:00 | × | on^ quits (~on@12.203.127.82) (Remote host closed the connection) |
| 16:52:53 | → | _ht joins (~quassel@82-169-194-8.biz.kpn.net) |
| 16:57:04 | × | raehik quits (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 265 seconds) |
| 16:57:45 | → | raehik joins (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) |
| 16:57:52 | × | Izem quits (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Quit: Izem) |
| 16:58:08 | → | Izem joins (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 17:00:41 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 17:01:47 | × | cfricke quits (~cfricke@user/cfricke) (Ping timeout: 252 seconds) |
| 17:02:12 | × | nschoe quits (~quassel@178.251.84.79) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.) |
| 17:02:18 | → | dsrt^ joins (~dsrt@12.203.127.82) |
| 17:07:49 | × | geekosaur quits (~geekosaur@xmonad/geekosaur) (Remote host closed the connection) |
| 17:10:01 | → | geekosaur joins (~geekosaur@xmonad/geekosaur) |
| 17:16:41 | <dminuoso> | monochrom: In English you can compose almost any two sentences, irrespective of whether it's sensible. There's also a man in the shadows with a gun in his eye. |
| 17:17:54 | <dminuoso> | Izem: I would read that as: forall a, where Read a, reads has type ReadS a. |
| 17:19:16 | <dminuoso> | monochrom: Im not sure how you teach Haskell, but I think having some uniform way to read out types can be useful at the beginning. It makes answering the question "what is the type of `xyz`" more sensible in a teaching scenario. |
| 17:19:54 | <monochrom> | I teach how to break it up. |
| 17:20:14 | <dminuoso> | I dont think of that above type signature as complicated enough to warrant breaking it up.. |
| 17:20:39 | <monochrom> | And the role of each part. |
| 17:20:42 | <Izem> | dminuoso: Is a an instance of Read? |
| 17:20:53 | <dminuoso> | Izem: It's *required* to have one. |
| 17:21:01 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Remote host closed the connection) |
| 17:21:21 | <dminuoso> | Izem: The thing with type variables is, the caller/user picks them. They are free to pick *any* type they want for them, as long as the specified constraints are satisfied. |
| 17:21:58 | <dminuoso> | So the user of `reads` can/has to pick any type they want, but their choice is limited to any type for which an `instance Read` exists. |
| 17:22:20 | <Izem> | ok |
| 17:22:24 | <dminuoso> | And its polymorphic. Hence my way of phrasing it "forall a, where Read a, reads has type ReadS a" |
| 17:22:32 | <dminuoso> | similarly: |
| 17:22:34 | <dminuoso> | % :t id |
| 17:22:34 | <yahb> | dminuoso: a -> a |
| 17:23:05 | <dminuoso> | Id say `id :: a -> a` as "forall a, id has type a to a" |
| 17:23:07 | <Izem> | id is in the environment already? |
| 17:23:21 | <Izem> | what does it do? |
| 17:23:27 | <monochrom> | I teach =>-less types first. That already is a long story on its own. There is parametric polymorphism. There is X->Y and X1->X2->Y, and I spend time showing that it means X1->(X2->Y), how it plays well with (f x1) x2, why it is useful. |
| 17:24:08 | <dminuoso> | Izem: `id` is a function that is made available in Prelude. It's one of the most simplistic functions you can think of, it just returns its argument. |
| 17:24:20 | <Izem> | ok |
| 17:24:25 | <monochrom> | After that, one is ready for classes and instances. After knowing classes and instances, "Read a =>" is not a mystery. |
| 17:24:51 | <awpr> | personally I pronounce the typeclass constraint arrow and the function arrow both as just "arrow". they're almost the same thing anyway, just that => takes Constraints on the lhs, is invisible/auto-solved in expressions, and is very enthusiastic to specialize |
| 17:24:56 | <dminuoso> | monochrom: Makes perfect sense. Perhaps I missed something, I had not conversed with Izem before. |
| 17:25:00 | <monochrom> | My view is that a plea for "what is it in English" stems from having none of the above preparation at all. |
| 17:25:05 | <dminuoso> | Judging by just that question, it seemed fair to ask. |
| 17:25:26 | <awpr> | but admittedly for learning it's probably easier to think of constraints as restrictions on allowable types |
| 17:25:27 | <dminuoso> | But if you have had prior interaction and knew their level of expertise (which perhaps is lower than I assumed).. |
| 17:25:50 | <monochrom> | As I said, the real question behind is fair to ask. The translation quesiton is an XY problem. Lots of students do it. |
| 17:27:03 | → | asivitz joins (uid178348@id-178348.tinside.irccloud.com) |
| 17:27:27 | <dminuoso> | awpr: Mmm, I dont think of the constraint arrow and function arrows as the same thing simply because they happen in different places. |
| 17:27:36 | <dminuoso> | One is a type checker level thing, the other is a runtime thing. |
| 17:27:47 | <dminuoso> | To equate them seems dangerously confusing. |
| 17:27:56 | <awpr> | they're both a runtime thing, unless GHC optimizes the constraint away |
| 17:28:21 | <awpr> | but GHC could equally well optimize away a function arrow, e.g. in spec-constr optimization |
| 17:28:28 | <dminuoso> | No it's still a type checking thing. |
| 17:28:34 | → | econo joins (uid147250@user/econo) |
| 17:28:40 | <awpr> | deciding what value to pass is a type-checker thing |
| 17:29:08 | <monochrom> | At any rate, I had already provided a translation before I explained why I objected. |
| 17:29:16 | <awpr> | actually receiving the instance dictionary is a runtime thing |
| 17:29:23 | <dminuoso> | monochrom: oh, I think I missed that singular line when I scrolled. |
| 17:29:29 | × | Izem quits (~Izem@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Quit: Izem) |
| 17:29:29 | <monochrom> | But here is the thing. |
| 17:29:55 | <dminuoso> | awpr: instance dictionary is an implementation detail. |
| 17:30:06 | <awpr> | heap object is an implementation detail |
| 17:30:08 | <monochrom> | If you don't have the prerequisite, the translation adds no predictive power. It is "helpful" only in the sense that it makes you feel good. |
| 17:30:13 | <dminuoso> | Yes, and I dont talk about heap objects. Your point being? |
| 17:30:33 | <monochrom> | If you have the prerequisite, you won't be asking in the first place. My students certainly don't. |
| 17:30:34 | <awpr> | they're still exactly the same construct at runtime, modulo optimizations |
| 17:31:09 | <awpr> | the only difference is in how it's determined at a given callsite what argument is actually passed |
| 17:31:37 | <awpr> | for (->) it's a visible argument, and for (=>) it's solved by constraint resolution |
| 17:31:38 | <monochrom> | Even when they're lost, my students ask more to-the-point questions, such as "what does the 'Read a =>' thing mean" or "where can I find out more about Read". |
| 17:31:38 | → | Izem joins (~Srain@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 17:31:59 | ← | Izem parts (~Srain@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) () |
| 17:32:33 | <dminuoso> | awpr: It starts being wrong already because of MMR. |
| 17:32:55 | <dminuoso> | Which is not just some "modulo optimization", its a builtin language feature with defined semantics |
| 17:32:55 | → | lavaman joins (~lavaman@98.38.249.169) |
| 17:33:56 | <awpr> | monomorphism restriction just constrains inferred types, no? |
| 17:34:25 | <awpr> | if the monomorphism restriction affects an expression, then its type doesn't involve a constraint anyway |
| 17:34:28 | <dminuoso> | It's to faciliate sharing |
| 17:34:40 | <dminuoso> | hold on |
| 17:34:52 | <dminuoso> | why doesnt it involve a constraint anyway? |
| 17:35:01 | × | azimut quits (~azimut@gateway/tor-sasl/azimut) (Remote host closed the connection) |
| 17:35:02 | <awpr> | because it's been monomorphized |
| 17:35:06 | <dminuoso> | So? |
| 17:35:19 | <dminuoso> | Num Int is a valid constraint to write, if you want. |
| 17:35:22 | → | azimut joins (~azimut@gateway/tor-sasl/azimut) |
| 17:35:37 | <awpr> | yes, but that constraint isn't part of the inferred type, it's solved immediately |
| 17:36:14 | <dminuoso> | So MMR makes this imaginary function go away? |
| 17:36:15 | → | ub joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 17:36:24 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 17:36:31 | <dminuoso> | So `Num Int => ...` is not a "function" but `Num a => ...` is? |
| 17:36:54 | <awpr> | there are two expressions that are relevant: the thing that causes the Num constraint, and the larger expression affected by MMR |
| 17:37:00 | <dminuoso> | I dont know, not sure what valuable insights you can gain from thinking of => as a function arrow. |
| 17:37:26 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 17:38:48 | → | jstolarek joins (~jstolarek@erx128.neoplus.adsl.tpnet.pl) |
| 17:39:40 | <awpr> | the effect of MMR is just that the inferred type is monomorphized, which usually results in the constraint solver being able to solve and immediately apply the inner term's constraint, so that it doesn't get propagated as a constraint on the inferred type |
| 17:39:59 | <monochrom> | There was a GHC bug. It was an accidental abstraction leak. It lets you write one of "Read a => String => a" or "Read a -> String -> a", I forgot which, but it was funny. |
| 17:40:35 | × | ub quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Ping timeout: 246 seconds) |
| 17:41:12 | <awpr> | I guess that happened around the time GHC was changed to have Constraint be literally the same thing as Type internally? |
| 17:41:59 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 17:43:00 | <monochrom> | Yeah something like that. |
| 17:43:15 | <monochrom> | ConstraintKind |
| 17:43:45 | <monochrom> | along with "kind is type too" etc |
| 17:43:45 | <awpr> | as for what insights: to me it seems to make parametricity clearer. having a constraint doesn't reduce the strength of parametricity by "magic" because it "makes fewer types legal arguments", it just adds a record argument containing the instance methods to the polytype |
| 17:46:37 | <awpr> | anyway I definitely think it's valuable to have the other view (constraints as limitations on polymorphism) as another angle, possibly even as the default way of looking at things, I just like to have both available |
| 17:47:04 | × | kuribas quits (~user@ptr-25vy0i747grimuk7ofw.18120a2.ip6.access.telenet.be) (Quit: ERC (IRC client for Emacs 26.3)) |
| 17:50:22 | <awpr> | oh, I missed a key part of one message: `Num Int => ...` is also (using the term loosely) a function. it's just that GHC won't ever infer that type and make that function, instead it'll immediately solve `Num Int` and apply it to the subexpression that needed it. if you spell out that constraint, I'm not sure whether GHC will actually do what you said or just optimize it out of existence; I should check |
| 17:50:46 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 17:50:50 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 17:51:04 | → | juhp joins (~juhp@128.106.188.220) |
| 17:52:51 | <monochrom> | I unify "static" and "dynamic" with hugs and ghci |
| 17:53:13 | <awpr> | yes, it will let you make that into an actual function: paste.tomsmeding.com/9DPBxuwa |
| 17:53:22 | <monochrom> | @quote lambdabot runghc |
| 17:53:22 | <lambdabot> | No quotes match. Listen, broccoli brains, I don't have time to listen to this trash. |
| 17:53:34 | <monochrom> | @quote monochrom runghc |
| 17:53:34 | <lambdabot> | monochrom says: just add #! /usr/bin/runghc to your haskell file. then type errors occur at runtime only. |
| 17:53:56 | <tomsmeding> | or -fdefer-type-errors |
| 17:54:06 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 265 seconds) |
| 17:54:16 | <monochrom> | Oh, it was a long time ago, -fdefer-type-errors did not exist. |
| 17:54:59 | <monochrom> | Also, probably s/with/by/ |
| 17:55:05 | <monochrom> | This is why I hate English. |
| 17:55:53 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 17:55:55 | → | cfricke joins (~cfricke@user/cfricke) |
| 17:56:08 | <monochrom> | awpr, did you need to turn on an extension, maybe FlexibleContext, to legalize Num Int? |
| 17:56:16 | <awpr> | yep, exactly that |
| 17:56:29 | <awpr> | ++'s' |
| 17:56:58 | <monochrom> | This is why I hate meaningful names cast in English. |
| 17:57:26 | <awpr> | GHC proposal: rename all language extensions into Lojban |
| 17:57:39 | <monochrom> | Chinese is a bit better in this regard, free of that kind of hair splitting. |
| 17:58:09 | <awpr> | no singular/plural distinction on the basic forms of nouns? |
| 17:58:18 | <monochrom> | None. |
| 17:58:26 | <monochrom> | And no preposition madness either. |
| 17:58:27 | <awpr> | cool, same reason I reached for Lojban |
| 17:59:14 | <awpr> | but I think Chinese might just slightly take the edge w.r.t. number of fluent speakers |
| 18:00:41 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 264 seconds) |
| 18:00:47 | <c_wraith> | I've heard that Chinese has an issue with reading and writing not being symmetric. A lot more native speakers can read than can write. (It's much easier to recognize characters than to remember them without a visual prompt) |
| 18:01:22 | <gehmehgeh> | Those Lojban language examples on Wikipedia look like something Cthulu would say :D |
| 18:01:35 | → | Brumaire joins (~quassel@81-64-14-121.rev.numericable.fr) |
| 18:01:39 | <gehmehgeh> | (I hadn't heard about Lojban und thought I look it up) |
| 18:01:58 | <monochrom> | I doubt it. I mean I doubt that it is more than other languages. |
| 18:02:57 | <geekosaur> | it used to be called logban, iirc |
| 18:03:04 | <geekosaur> | er, loglan |
| 18:03:22 | <monochrom> | Any of you claim you have the same fluency in writing "zygomorphism" as you are fluent in reading it? |
| 18:03:33 | <c_wraith> | synthetic words like that are easy to write |
| 18:03:53 | geekosaur | has less problem reading or writing it than understanding it |
| 18:03:55 | <c_wraith> | the difficulty in writing in English is when you *don't* know where the loan words originate |
| 18:05:46 | <geekosaur> | yoğurt |
| 18:06:17 | <monochrom> | OK, people mix up "effect" and "affect". |
| 18:06:55 | <gehmehgeh> | inapt and inept :D |
| 18:06:56 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 18:07:27 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 18:07:28 | <gehmehgeh> | (Tought, inapt and inept at least sound different) |
| 18:08:04 | <monochrom> | You know, to someone like me with ESL background, they sound too similar. |
| 18:08:21 | → | favonia joins (~favonia@user/favonia) |
| 18:09:08 | <monochrom> | Generally we have difficulty distinguishing, or reproducing the difference of, "at" and "et". |
| 18:09:30 | <monochrom> | Some of us can't even draw a line between "name" and "nam". |
| 18:09:57 | <monochrom> | You will hear some of us saying "my nam is monochrom, I like to play gams". |
| 18:11:05 | <Rembane> | manachram! |
| 18:11:06 | Rembane | nods |
| 18:12:46 | <geekosaur> | I find that interesting because, so far as English has reliable rules, that's one of them |
| 18:14:09 | <monochrom> | But there is something about, it takes several years, and a very young and plastic brain, to train to recognize that there is a difference. |
| 18:14:16 | <monochrom> | any difference. |
| 18:14:53 | <monochrom> | I have trouble telling apart red hair and blonde hair. This is why I didn't see enough examples when I was a child. |
| 18:15:03 | <gehmehgeh> | monochrom: what dialect/variant of the English language are you speaking? |
| 18:15:27 | <monochrom> | s/why/because/ |
| 18:16:29 | <monochrom> | You will have trouble telling apart, say, Chinese faces from Japanese faces from Korean faces. This is because you didn't see enough examples when you were a child. East Asian people like me can tell them apart, we saw enough examples. |
| 18:16:42 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 18:16:50 | <gehmehgeh> | monochrom: I think I can tell them apart, too. |
| 18:16:53 | <gehmehgeh> | monochrom: I'm from Germany |
| 18:17:19 | <gehmehgeh> | That is, generally. Some people have faces that could come from anywhere |
| 18:17:19 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 18:17:19 | <monochrom> | I don't know. I started in Hong Kong. I am in Canada. I have heard British, American, Canadian, perhaps also Singapore and Polish. |
| 18:17:42 | <ldlework> | awpr: did you see the latest graph |
| 18:17:45 | <geekosaur> | "American" has plenty of dialects all by itself |
| 18:18:00 | <gehmehgeh> | Canadian being one of them ;) |
| 18:18:31 | <awpr> | ldlework: I think so, with 14 classes and full method listings for them? |
| 18:18:37 | <monochrom> | I had a prof from Singapore who pronouced "library" by putting the accent on the "y". |
| 18:18:45 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 18:18:46 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 18:18:56 | <ldlework> | yeah this one https://github.com/dustinlacewell/haskell-typeclass-atlas/blob/master/atlas.png?raw=true |
| 18:19:05 | <awpr> | y |
| 18:19:15 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 18:20:07 | <monochrom> | So imagine "comprehend" applied to "library" |
| 18:24:18 | <monochrom> | Nice class atlas. |
| 18:24:43 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 252 seconds) |
| 18:25:28 | <monochrom> | Ugh where are Bounded, Enum, Show, Read? :) |
| 18:26:26 | × | gehmehgeh quits (~user@user/gehmehgeh) (Quit: Leaving) |
| 18:27:41 | <zzz> | what's a good resource to learn about kind signatures? |
| 18:31:11 | → | amahl joins (~amahl@dsl-jklbng12-54fbca-64.dhcp.inet.fi) |
| 18:31:59 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Ping timeout: 252 seconds) |
| 18:33:06 | → | gehmehgeh joins (~user@user/gehmehgeh) |
| 18:34:53 | × | lavaman quits (~lavaman@98.38.249.169) (Ping timeout: 264 seconds) |
| 18:36:19 | <Franciman> | is there a way to make cabal output Core code of the files in the project? |
| 18:37:02 | <awpr> | does `ghc-options: -ddump-simpl` work? |
| 18:37:19 | → | neurocyte013 joins (~neurocyte@212.232.95.106) |
| 18:37:19 | × | neurocyte013 quits (~neurocyte@212.232.95.106) (Changing host) |
| 18:37:19 | → | neurocyte013 joins (~neurocyte@user/neurocyte) |
| 18:37:56 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 18:41:48 | × | neurocyte013 quits (~neurocyte@user/neurocyte) (Client Quit) |
| 18:43:09 | → | neurocyte013 joins (~neurocyte@212.232.95.106) |
| 18:43:09 | × | neurocyte013 quits (~neurocyte@212.232.95.106) (Changing host) |
| 18:43:09 | → | neurocyte013 joins (~neurocyte@user/neurocyte) |
| 18:43:34 | × | viluon quits (uid453725@id-453725.helmsley.irccloud.com) (Quit: Connection closed for inactivity) |
| 18:49:53 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 18:49:56 | × | mikoto-chan quits (~mikoto-ch@ip-83-134-2-136.dsl.scarlet.be) (Quit: mikoto-chan) |
| 18:50:14 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 18:53:01 | × | ubert quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Remote host closed the connection) |
| 18:56:21 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 18:56:44 | × | cfricke quits (~cfricke@user/cfricke) (Ping timeout: 252 seconds) |
| 18:57:20 | → | ubert joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 19:00:04 | × | oxide quits (~lambda@user/oxide) (Quit: oxide) |
| 19:03:00 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 19:04:12 | × | Cajun quits (~Cajun@user/cajun) (Quit: Client closed) |
| 19:07:39 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Remote host closed the connection) |
| 19:09:21 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 19:12:14 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 19:12:14 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 19:12:14 | → | wroathe joins (~wroathe@user/wroathe) |
| 19:16:25 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 252 seconds) |
| 19:26:35 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 19:32:06 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 19:32:15 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 19:33:29 | → | dschrempf joins (~dominik@070-207.dynamic.dsl.fonira.net) |
| 19:39:38 | × | dhouthoo quits (~dhouthoo@178-117-36-167.access.telenet.be) (Quit: WeeChat 3.2) |
| 19:41:50 | → | favonia joins (~favonia@user/favonia) |
| 19:45:06 | × | Vajb quits (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) (Read error: Connection reset by peer) |
| 19:46:10 | → | Vajb joins (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) |
| 19:46:11 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 19:46:24 | → | juhp joins (~juhp@128.106.188.220) |
| 19:46:44 | → | Izem joins (~user@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 19:47:16 | → | TranquilEcho joins (~grom@user/tranquilecho) |
| 19:51:07 | × | bonizzi quits (~bonizzi@2804:14c:65d3:4689:d52e:1289:d36a:ed19) (Quit: Leaving) |
| 19:51:31 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 19:51:44 | → | juhp joins (~juhp@128.106.188.220) |
| 19:53:05 | × | ubert quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Quit: ubert) |
| 19:53:17 | → | ubert joins (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) |
| 19:53:49 | × | geekosaur quits (~geekosaur@xmonad/geekosaur) (Remote host closed the connection) |
| 19:54:09 | → | geekosaur joins (~geekosaur@xmonad/geekosaur) |
| 19:55:04 | × | ubert quits (~Thunderbi@77.119.204.226.wireless.dyn.drei.com) (Remote host closed the connection) |
| 19:55:53 | <maerwald> | monochrom: lol, senglish is awesome |
| 19:56:00 | <maerwald> | can |
| 19:57:20 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 19:59:53 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 20:00:03 | <ixlun> | Is there a 'standard' way of representing 0 with Rational? |
| 20:00:17 | <ixlun> | I'm using `0 % 1`, but is there a standard? |
| 20:01:41 | <geekosaur> | 0 % 1, or just write 0 and let Num literal magic do its thing |
| 20:02:11 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 20:03:18 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 20:04:20 | <ixlun> | Ah, didn't know I could do `0 :: Rational` and that woeks. Neat! |
| 20:04:24 | × | _ht quits (~quassel@82-169-194-8.biz.kpn.net) (Remote host closed the connection) |
| 20:05:22 | × | juhp quits (~juhp@128.106.188.220) (Ping timeout: 252 seconds) |
| 20:05:29 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 252 seconds) |
| 20:06:17 | × | amahl quits (~amahl@dsl-jklbng12-54fbca-64.dhcp.inet.fi) (Quit: Leaving) |
| 20:06:53 | → | TDANG joins (~TDANG@inet-177-7.ets.org) |
| 20:07:05 | → | juhp joins (~juhp@128.106.188.220) |
| 20:07:10 | → | acidjnk joins (~acidjnk@p200300d0c703cb44319f4c33bc64626e.dip0.t-ipconnect.de) |
| 20:07:17 | × | xff0x quits (~xff0x@2001:1a81:53a2:cb00:c07c:d089:8b2f:814c) (Ping timeout: 264 seconds) |
| 20:07:39 | → | xff0x joins (~xff0x@2001:1a81:53a2:cb00:fe64:bcbc:d8a9:c1f9) |
| 20:07:41 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 20:10:49 | → | pavonia joins (~user@user/siracusa) |
| 20:12:17 | <TDANG> | hi everybody |
| 20:12:37 | <TDANG> | I don't understand the : symbol |
| 20:12:44 | <TDANG> | (single colon) |
| 20:12:54 | <c_wraith> | What resources have you used for learning the language? |
| 20:13:21 | <TDANG> | http://learnyouahaskell.com/ |
| 20:14:58 | <c_wraith> | It's covered in the "intro to lists" section. Did you get to that part? |
| 20:16:54 | <TDANG> | great, I found it. |
| 20:17:08 | <c_wraith> | (If you did and things don't make sense, that's fine. I'm just trying to get a baseline of what you're looking for) |
| 20:17:13 | <TDANG> | I'll go with it. Thanks ;-) |
| 20:17:35 | × | jstolarek quits (~jstolarek@erx128.neoplus.adsl.tpnet.pl) (Ping timeout: 252 seconds) |
| 20:19:45 | → | TDANG_ joins (~TDANG@cpe-107-15-144-45.nc.res.rr.com) |
| 20:21:21 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 20:21:41 | × | TDANG quits (~TDANG@inet-177-7.ets.org) (Ping timeout: 264 seconds) |
| 20:21:58 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 20:21:59 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 20:21:59 | → | wroathe joins (~wroathe@user/wroathe) |
| 20:25:17 | × | michalz quits (~michalz@185.246.204.33) (Remote host closed the connection) |
| 20:26:50 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 265 seconds) |
| 20:27:59 | → | Pickchea joins (~private@user/pickchea) |
| 20:33:41 | × | Izem quits (~user@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) (Ping timeout: 264 seconds) |
| 20:33:51 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 20:34:16 | → | Tuplanolla joins (~Tuplanoll@91-159-69-50.elisa-laajakaista.fi) |
| 20:39:10 | → | Cajun joins (~Cajun@user/cajun) |
| 20:39:37 | → | nschoe joins (~quassel@2a01:e0a:8e:a190:1aae:e766:24c4:a2ba) |
| 20:40:52 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 20:41:05 | × | ystael quits (~ystael@user/ystael) (Read error: Connection reset by peer) |
| 20:43:43 | × | rond_ quits (~rond_@2a02:a31a:a23c:f480:2fd7:e087:5546:a438) (Quit: Client closed) |
| 20:47:11 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 20:47:24 | → | juhp joins (~juhp@128.106.188.220) |
| 20:48:08 | → | ystael joins (~ystael@user/ystael) |
| 20:48:31 | × | takuan quits (~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection) |
| 20:50:54 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 260 seconds) |
| 20:52:37 | <monochrom> | Oh hey, "newtype P m a = MkP{unP :: String -> m (String, a)}". If m is an instance of MonadPlus and Alternative, then P m is a parser monad! Typically m = [] or Maybe or Either X. |
| 20:53:21 | <awpr> | > :i ST |
| 20:53:23 | <lambdabot> | <hint>:1:1: error: parse error on input ‘:’ |
| 20:53:47 | <monochrom> | Sacrilegeous idea: Let me inflict this much generality on my students next time >:) |
| 20:53:55 | <awpr> | ah, not MonadPlus |
| 20:54:19 | <monochrom> | Heh, IO actually has a chance >:) |
| 20:54:26 | <awpr> | oh duh, I meant STM, but that's also not MonadPlus |
| 20:54:35 | × | Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Read error: Connection reset by peer) |
| 20:55:01 | <awpr> | or... it is, but my ghci doesn't know it |
| 20:55:25 | <monochrom> | I suppose I don't need MonadPlus. I just need Monad and Alternative. |
| 20:55:31 | → | Lord_of_Life joins (~Lord@user/lord-of-life/x-2819915) |
| 20:55:32 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 252 seconds) |
| 20:55:42 | <awpr> | so that would retry a transaction until the parse succeeded? :D |
| 20:55:43 | <monochrom> | Oh heh yeah you need to import more modules, or use :info! |
| 20:56:05 | <awpr> | oh, no, it would avoid retrying |
| 20:56:08 | <monochrom> | Haha questionable use cases, but the math works out! |
| 20:57:31 | × | juhp quits (~juhp@128.106.188.220) (Quit: juhp) |
| 20:57:45 | → | juhp joins (~juhp@128.106.188.220) |
| 20:58:54 | <awpr> | now I'm picturing a compiler that just deadlocks until you update the file with correct input |
| 20:59:57 | <monochrom> | Heh |
| 21:02:47 | × | hiepph[m] quits (~hiepphmat@2001:470:69fc:105::e3a8) (Ping timeout: 240 seconds) |
| 21:03:34 | × | Jon quits (jon@dow.land) (Quit: ZNC - http://znc.in) |
| 21:03:46 | → | hiepph[m] joins (~hiepphmat@2001:470:69fc:105::e3a8) |
| 21:04:10 | → | Jon joins (jon@dow.land) |
| 21:04:20 | × | wonko quits (~wjc@62.115.229.50) (Ping timeout: 252 seconds) |
| 21:05:03 | × | gioyik quits (~gioyik@gateway/tor-sasl/gioyik) (Ping timeout: 276 seconds) |
| 21:06:00 | → | Izem joins (~user@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) |
| 21:06:21 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 21:06:50 | → | Lord_of_Life_ joins (~Lord@user/lord-of-life/x-2819915) |
| 21:06:51 | ← | Izem parts (~user@bras-base-london1483w-grc-31-74-12-158-179.dsl.bell.ca) () |
| 21:07:47 | × | Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 246 seconds) |
| 21:08:06 | Lord_of_Life_ | is now known as Lord_of_Life |
| 21:08:11 | × | Brumaire quits (~quassel@81-64-14-121.rev.numericable.fr) (Ping timeout: 252 seconds) |
| 21:08:40 | → | azeem joins (~azeem@2a00:801:3c7:f4f5:1ae6:c0ab:f962:792a) |
| 21:09:57 | → | Nosrep joins (~archbox@user/nosrep) |
| 21:10:43 | → | favonia joins (~favonia@user/favonia) |
| 21:12:50 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 21:13:42 | × | MQ-17J quits (~MQ-17J@d192-24-122-179.try.wideopenwest.com) (Read error: Connection reset by peer) |
| 21:14:06 | → | MQ-17J joins (~MQ-17J@8.21.10.6) |
| 21:19:01 | × | Everything quits (~Everythin@37.115.210.35) (Quit: leaving) |
| 21:20:42 | → | maroloccio joins (~marolocci@93-142-92-177.adsl.net.t-com.hr) |
| 21:23:24 | <monochrom> | > let a \~ b = a-b in 5 \~ 3 |
| 21:23:25 | <lambdabot> | 2 |
| 21:24:10 | <monochrom> | This means "\~(a,b) -> (b,a)" is a parse error, the computer doesn't see it as "lambda, lazy pattern". |
| 21:24:23 | × | jespada quits (~jespada@2803:9800:9842:7a62:edd5:5e74:3ec2:1b19) (Quit: My MacBook has gone to sleep. ZZZzzz…) |
| 21:24:28 | <monochrom> | Hrm does Haskell accept zero-width space? >:) |
| 21:24:44 | <geekosaur> | I thought someone tried that the other day and it didn't? |
| 21:25:10 | <hpc> | > (\(~(a,b)) -> a) (1, 2) |
| 21:25:12 | <lambdabot> | 1 |
| 21:25:29 | <hpc> | the lisp solution |
| 21:25:32 | <hpc> | when in doubt, add parens |
| 21:26:26 | → | jespada joins (~jespada@2803:9800:9842:7a62:4d47:2975:7b31:a447) |
| 21:26:26 | <monochrom> | Oh I guess "U+FEFF ZERO WIDTH NO-BREAK SPACE" is aka byte-order marker. |
| 21:26:49 | <awpr> | ohhh that's clever, I hate it |
| 21:27:15 | × | favonia quits (~favonia@user/favonia) (Ping timeout: 265 seconds) |
| 21:27:25 | <awpr> | if some software isn't aware of BOMs, it harmlessly decays into a zero-width invisible character at the start of the document |
| 21:27:56 | <monochrom> | Unless it's cassava, which is totally thrown off by that. |
| 21:29:30 | <monochrom> | The tension here is that a lot of CSV-producing software honours the Windows convention of: 1. UTF-8 (that's good), 2. CRLF (that's fine, the CSV standard prescribe it anyway), 3. BOM (ugh). |
| 21:29:31 | × | Vajb quits (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) (Read error: Connection reset by peer) |
| 21:29:46 | → | Vajb joins (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) |
| 21:29:55 | <geekosaur> | the problem with BOM is it's not UTF8 |
| 21:30:22 | <geekosaur> | (as windows uses it, at least) |
| 21:30:29 | <awpr> | wait do they not use the UTF-8 encoding of that character? |
| 21:30:35 | × | flouflou quits (~flouflou@modemcable032.110-177-173.mc.videotron.ca) (Quit: WeeChat 3.2) |
| 21:30:40 | <geekosaur> | nope |
| 21:30:48 | <geekosaur> | it's UTF16 |
| 21:30:55 | <awpr> | just throw a singular completely irrelevant UCS-2 thing at the start of a UTF-8 file? |
| 21:31:18 | <geekosaur> | windows was at the time trying to be sorta kinda utf16 |
| 21:31:39 | <geekosaur> | then went utf8 later but kept the same BONM it had been using |
| 21:31:53 | <awpr> | I can't even fathom |
| 21:32:13 | <hpc> | the codepoint is still valid, it's just not useful because there aren't multiple ways to write utf8 |
| 21:32:21 | <hpc> | so in that sense they're technically fine |
| 21:32:21 | → | gioyik joins (~gioyik@gateway/tor-sasl/gioyik) |
| 21:32:25 | <monochrom> | They use the UTF-8 encoding of that character for UTF-8 files. Yes. |
| 21:32:26 | <cdsmith> | Is there a way for a Haskell process to find the RTS args that were passed to it? They are removed from the normal System.Environment.getArgs. |
| 21:32:36 | <awpr> | monochrom: oh, okay. seems alright then |
| 21:32:40 | <awpr> | if unnecessary |
| 21:32:47 | <glguy> | cdsmith: they are removed from getArgs |
| 21:32:53 | <monochrom> | They then use the UTF-16?E of the character for UTF-16?E files, correspondinging. |
| 21:32:53 | <geekosaur> | oh, they do now? |
| 21:33:05 | × | pbrisbin quits (~patrick@pool-173-49-147-250.phlapa.fios.verizon.net) (Ping timeout: 264 seconds) |
| 21:33:06 | <geekosaur> | at one point they weren't |
| 21:33:13 | <geekosaur> | which was really annoying |
| 21:33:33 | <monochrom> | They have always done, as far as I have worked with CSV files I have received since several years ago. |
| 21:34:20 | <monochrom> | My own code does a BL.stripPrefix (BL.pack "\xef\xbb\xbf") bytes, I have never need to strip "\xfe\xff" or something. |
| 21:34:47 | <monochrom> | Ah OK must be way before my time. |
| 21:34:48 | <cdsmith> | glguy: Yes, I know. Was hoping there's some way to get them anyway. |
| 21:34:53 | × | Gurkenglas quits (~Gurkengla@dslb-002-207-014-195.002.207.pools.vodafone-ip.de) (Ping timeout: 264 seconds) |
| 21:35:21 | × | chomwitt quits (~chomwitt@2a02:587:dc15:500:12c3:7bff:fe6d:d374) (Read error: Connection reset by peer) |
| 21:35:29 | → | aliosablack joins (~chomwitt@2a02:587:dc15:500:12c3:7bff:fe6d:d374) |
| 21:35:36 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 21:35:54 | <monochrom> | Does GHC.Environment.getFullArgs help? |
| 21:36:25 | <glguy> | cdsmith: I think you'll need to start digging in something like this: https://hackage.haskell.org/package/base-4.15.0.0/docs/src/GHC-RTS-Flags.html#getRTSFlags |
| 21:38:28 | × | nschoe quits (~quassel@2a01:e0a:8e:a190:1aae:e766:24c4:a2ba) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.) |
| 21:39:01 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 21:41:45 | × | shachaf quits (~shachaf@user/shachaf) (Ping timeout: 265 seconds) |
| 21:42:22 | → | shachaf joins (~shachaf@user/shachaf) |
| 21:42:26 | × | aliosablack quits (~chomwitt@2a02:587:dc15:500:12c3:7bff:fe6d:d374) (Ping timeout: 246 seconds) |
| 21:42:39 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 21:43:12 | × | gehmehgeh quits (~user@user/gehmehgeh) (Quit: Leaving) |
| 21:43:53 | × | merijn quits (~merijn@83-160-49-249.ip.xs4all.nl) (Ping timeout: 264 seconds) |
| 21:46:36 | → | Lycurgus joins (~juan@98.4.112.204) |
| 21:46:44 | <cdsmith> | glguy: Hmm, getting that back into String form looks challenging. C FFI might be a better bet at that point. :( |
| 21:48:05 | <cdsmith> | Well, that's what I needed to know. Thank you. I think I need to find a different way. |
| 21:48:09 | <geekosaur> | did you see monochrom's suggestion |
| 21:48:11 | <geekosaur> | ? |
| 21:48:31 | <cdsmith> | Oh, no! |
| 21:48:31 | <cdsmith> | I'll look |
| 21:49:00 | <cdsmith> | Perfect. Thanks monochrom |
| 21:53:53 | <glguy> | To get just the RTS arguments: https://gist.github.com/glguy/7a5ae553f463aa7d2c7e786180b9d085 <_< |
| 21:54:44 | <monochrom> | could be worse :) |
| 21:54:46 | <ldlework> | glguy: do you use opengl with haskell |
| 21:55:30 | <geekosaur> | actually, strictly speaking both of those only get RTS options from the command line, not $GHCRTS or compiled-in rtsopts |
| 21:56:00 | <ldlework> | oh "good luck, guy" maybe, nm |
| 21:56:31 | <glguy> | I think I have done some OpenGL from Haskell, but very little. |
| 21:56:39 | × | eggplantade quits (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) (Remote host closed the connection) |
| 21:58:34 | × | mousey quits (~sky@gateway/tor-sasl/mousey) (Remote host closed the connection) |
| 21:58:55 | → | yauhsien joins (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) |
| 21:59:05 | → | Arathorn joins (~arathorn@2001:470:69fc:105::1f) |
| 21:59:29 | × | cheater quits (~Username@user/cheater) (Ping timeout: 264 seconds) |
| 22:00:04 | × | dschrempf quits (~dominik@070-207.dynamic.dsl.fonira.net) (Quit: WeeChat 3.2.1) |
| 22:00:51 | × | max22- quits (~maxime@2a01cb08833598000f1fa44417d80ccf.ipv6.abo.wanadoo.fr) (Quit: Leaving) |
| 22:02:54 | → | cheater joins (~Username@user/cheater) |
| 22:03:37 | × | yauhsien quits (~yauhsien@118-167-47-202.dynamic-ip.hinet.net) (Ping timeout: 252 seconds) |
| 22:05:30 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 22:06:37 | × | __monty__ quits (~toonn@user/toonn) (Quit: leaving) |
| 22:10:52 | → | son0p joins (~ff@181.136.122.143) |
| 22:12:37 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 22:15:37 | × | Vajb quits (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) (Read error: Connection reset by peer) |
| 22:16:48 | × | Pickchea quits (~private@user/pickchea) (Quit: Leaving) |
| 22:18:17 | → | Morrow joins (~MorrowM_@bzq-110-168-31-106.red.bezeqint.net) |
| 22:26:26 | → | werneta joins (~werneta@70-142-214-115.lightspeed.irvnca.sbcglobal.net) |
| 22:28:14 | → | eggplantade joins (~Eggplanta@2600:1700:bef1:5e10:1c28:7782:3d08:8ee5) |
| 22:29:15 | <cdsmith> | glguy: Getting all arguments was actually perfect for my use. https://github.com/haskell/haskell-language-server/pull/2228 |
| 22:31:02 | → | Vajb joins (~Vajb@hag-jnsbng11-58c3a8-176.dhcp.inet.fi) |
| 22:33:21 | <glguy> | It seems like you'd want the arguments to not be interpreted by the wrapper and *only* passed through |
| 22:34:35 | <glguy> | passing through the ones handled by the wrapper itself means that, for example, things that write to files (like -t) will cause two different runtimes to write to that file |
| 22:40:55 | → | wroathe joins (~wroathe@96-88-30-181-static.hfc.comcastbusiness.net) |
| 22:40:55 | × | wroathe quits (~wroathe@96-88-30-181-static.hfc.comcastbusiness.net) (Changing host) |
| 22:40:55 | → | wroathe joins (~wroathe@user/wroathe) |
| 22:48:06 | <monochrom> | w00t new ghcup |
| 22:50:21 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 22:54:05 | × | nfd quits (~nfd@user/nfd) (Ping timeout: 264 seconds) |
| 22:54:40 | × | Tuplanolla quits (~Tuplanoll@91-159-69-50.elisa-laajakaista.fi) (Quit: Leaving.) |
| 22:55:13 | × | MQ-17J quits (~MQ-17J@8.21.10.6) (Ping timeout: 265 seconds) |
| 22:55:46 | × | maroloccio quits (~marolocci@93-142-92-177.adsl.net.t-com.hr) (Quit: WeeChat 3.0) |
| 22:56:57 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 22:58:37 | → | MQ-17J joins (~MQ-17J@d192-24-122-179.try.wideopenwest.com) |
| 23:12:55 | × | Lycurgus quits (~juan@98.4.112.204) (Quit: Exeunt) |
| 23:18:22 | <geekosaur> | wee, big upgrade completed and xmonad now happily runniung based on 8.10.7 instead of 8.10.4 |
| 23:18:42 | <geekosaur> | other utils can wait, they'll rebuild as needed anyway |
| 23:19:17 | <geekosaur> | cabal++ |
| 23:20:25 | <hpc> | cabal# .net |
| 23:24:59 | → | kimjetwav joins (~user@2607:fea8:235f:9730:158b:8b68:ef55:bdbf) |
| 23:27:17 | <shapr> | yay xmonad! |
| 23:28:01 | → | hiruji` joins (~hiruji@72.74.190.75) |
| 23:28:17 | × | acidjnk quits (~acidjnk@p200300d0c703cb44319f4c33bc64626e.dip0.t-ipconnect.de) (Ping timeout: 264 seconds) |
| 23:28:17 | × | hiruji quits (~hiruji@user/hiruji) (Ping timeout: 264 seconds) |
| 23:33:26 | × | mc47 quits (~mc47@xmonad/TheMC47) (Remote host closed the connection) |
| 23:33:35 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 23:35:12 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 276 seconds) |
| 23:36:11 | × | TranquilEcho quits (~grom@user/tranquilecho) (Quit: WeeChat 2.8) |
| 23:37:58 | × | hiruji` quits (~hiruji@72.74.190.75) (Quit: ZNC 1.8.2 - https://znc.in) |
| 23:38:16 | → | hiruji joins (~hiruji@user/hiruji) |
| 23:41:29 | × | wroathe quits (~wroathe@user/wroathe) (Ping timeout: 264 seconds) |
| 23:42:08 | × | raehik quits (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 246 seconds) |
| 23:42:10 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 23:42:19 | × | geekosaur quits (~geekosaur@xmonad/geekosaur) (Remote host closed the connection) |
| 23:42:39 | → | geekosaur joins (~geekosaur@xmonad/geekosaur) |
| 23:42:48 | → | raehik joins (~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) |
| 23:43:08 | × | hiruji quits (~hiruji@user/hiruji) (Client Quit) |
| 23:43:09 | → | merijn joins (~merijn@83-160-49-249.ip.xs4all.nl) |
| 23:49:25 | × | asivitz quits (uid178348@id-178348.tinside.irccloud.com) (Quit: Connection closed for inactivity) |
| 23:51:06 | × | pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Quit: WeeChat 3.3) |
| 23:57:03 | → | wroathe joins (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) |
| 23:57:03 | × | wroathe quits (~wroathe@c-68-54-25-135.hsd1.mn.comcast.net) (Changing host) |
| 23:57:03 | → | wroathe joins (~wroathe@user/wroathe) |
All times are in UTC on 2021-09-21.