Home liberachat/#haskell: Logs Calendar

Logs on 2023-11-15 (liberachat/#haskell)

00:10:47 × landonf quits (landonf@mac68k.info) (Server closed connection)
00:10:56 landonf joins (landonf@mac68k.info)
00:10:57 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)
00:10:59 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Ping timeout: 252 seconds)
00:12:39 × thegeekinside quits (~thegeekin@189.141.80.123) (Remote host closed the connection)
00:20:24 johnw joins (~johnw@69.62.242.138)
00:22:23 Sgeo joins (~Sgeo@user/sgeo)
00:25:51 × sawilagar quits (~sawilagar@user/sawilagar) (Ping timeout: 260 seconds)
00:30:00 Guest21 joins (~Guest21@178.255.149.181)
00:30:00 × immae quits (~immae@2a01:4f8:141:53e7::) (Server closed connection)
00:30:19 immae joins (~immae@2a01:4f8:141:53e7::)
00:34:03 yosef` joins (~yosef`@user/yosef/x-2947716)
00:34:21 thegeekinside joins (~thegeekin@189.141.80.123)
00:47:59 <Guest21> hi. i'm not sure if this is the best place to ask this, but i'm encountering problems while trying to install readline through cabal on macos. i already installed readline through brew and it currently sits at: `/opt/homebrew/Cellar/readline/8.2.1/` . after numerous threads about the issue, i ended up at following command (which seemed to work for
00:48:00 <Guest21> some people): https://paste.tomsmeding.com/X27wQMlq. unfortunately the logs (https://paste.tomsmeding.com/kP4Zf2Yo) say that readline wasn't found. i can't figure out what's wrong here, does anyone have a clue?
00:52:32 <EvanR> try closing the terminal in case environment variables haven't updated
00:53:39 <Guest21> unfortunately it doesn't work. logs stay the same
00:54:29 × thaumavorio quits (~thaumavor@thaumavor.io) (Server closed connection)
00:55:49 thaumavorio joins (~thaumavor@thaumavor.io)
00:58:56 × yosef` quits (~yosef`@user/yosef/x-2947716) (Remote host closed the connection)
00:59:15 <geekosaur> actually that log says it was found, but is apparently the wrong version
00:59:36 yosef` joins (~yosef`@user/yosef/x-2947716)
00:59:55 <geekosaur> it has rl_readline_version but not rl_begin_undo_group
01:00:23 <geekosaur> (the earlier failure was llooking for a different variety of readline install, via a MacOS framework instead of a normal library)
01:01:11 × califax quits (~califax@user/califx) (Remote host closed the connection)
01:01:15 <mauke> according to the configure script, this means "-lreadline" is actually libedit
01:01:26 <mauke> the "readline not found" error is generic
01:01:38 <mauke> so it's finding the wrong library
01:01:59 califax joins (~califax@user/califx)
01:03:51 <Guest21> is the problem here with order of search locations? first it goes for system location where it finds libedit without all necessary features and then it would search the extra locations?
01:03:57 <mauke> Guest21: vague idea: what does 'ls -l /opt/homebrew/Cellar/readline/8.2.1/lib' report?
01:04:05 notzmv joins (~zmv@user/notzmv)
01:04:34 × yosef` quits (~yosef`@user/yosef/x-2947716) (Remote host closed the connection)
01:05:07 <Guest21> `-r--r--r--@ 1 user admin 91888 Nov 15 00:38 libhistory.8.2.dylib`
01:05:08 <Guest21> `lrwxr-xr-x@ 1 user admin 20 Sep 23 2022 libhistory.8.dylib@ -> libhistory.8.2.dylib`
01:05:08 <Guest21> `-r--r--r--@ 1 user admin 46504 Sep 23 2022 libhistory.a`
01:05:09 <Guest21> `lrwxr-xr-x@ 1 user admin 20 Sep 23 2022 libhistory.dylib@ -> libhistory.8.2.dylib`
01:05:09 <Guest21> `-rw-r--r--@ 1 user admin 311648 Nov 15 00:38 libreadline.8.2.dylib`
01:05:10 <Guest21> `lrwxr-xr-x@ 1 user admin 21 Sep 23 2022 libreadline.8.dylib@ -> libreadline.8.2.dylib`
01:05:10 <Guest21> `-r--r--r--@ 1 user admin 468504 Sep 23 2022 libreadline.a`
01:05:11 <Guest21> `lrwxr-xr-x@ 1 user admin 21 Sep 23 2022 libreadline.dylib@ -> libreadline.8.2.dylib`
01:05:11 <Guest21> `drwxr-xr-x@ 4 user admin 128 Nov 15 00:38 pkgconfig/`
01:05:12 <Guest21> i'm sorry, is there a multiline quote?
01:05:23 × noteness quits (~noteness@user/noteness) (Server closed connection)
01:05:28 <EvanR> OOF
01:06:27 <mauke> as a general rule, don't paste into IRC (beyond a single line). we use paste sites for that
01:06:30 <geekosaur> not in IRC; use a pastebin
01:06:33 <geekosaur> @where paste
01:06:33 <lambdabot> Help us help you: please paste full code, input and/or output at e.g. https://paste.tomsmeding.com
01:06:39 noteness joins (~noteness@user/noteness)
01:06:45 <Guest21> https://paste.tomsmeding.com/ClRzpeMh
01:09:12 <mauke> looks normal to me
01:09:52 <geekosaur> looks reasonable to me as well, granting it's been several years since I dealt with Macs
01:10:26 <mauke> for fun, you could try 'nm /opt/homebrew/Cellar/readline/8.2.1/lib/libreadline.a | grep rl_begin_undo_group', but I'm not sure what nm output looks like on macos
01:11:32 × dostoyevsky2 quits (~sck@user/dostoyevsky2) (Server closed connection)
01:11:37 <mauke> on my linux system, the output contains "00000000000004d0 T rl_begin_undo_group", indicating that the symbol is defined somewhere in the "T"ext section
01:11:41 <Guest21> mauke: https://paste.tomsmeding.com/WWuZfqAw
01:11:42 dostoyevsky2 joins (~sck@user/dostoyevsky2)
01:12:13 <mauke> ah, decorated with a leading underscore
01:12:18 <geekosaur> what's worrying me is that recentish MacOS has this system loader cache thing that might be overriding the actual selected library
01:12:43 <geekosaur> although it's more likely that it's just not looking where it was told to for some reason
01:14:08 <geekosaur> hm, actually I wonder if that command line works with v2-install
01:14:19 <geekosaur> which is intended for binaries, not libraries
01:15:32 <geekosaur> (if you have cabal 3.x, install is v2-install)
01:16:13 <Guest21> wow, it worked with v1-install
01:16:15 <Guest21> thank you
01:16:51 <geekosaur> right, but anything you build that depends on it won't work unless you use v1-install for those
01:19:44 × talismanick quits (~user@campus-116-122.ucdavis.edu) (Ping timeout: 252 seconds)
01:20:41 <geekosaur> I think for v2 install you need a cabal.project.local that looks like https://paste.tomsmeding.com/Xe1savDh
01:21:13 <geekosaur> lemme doublecheck that configure-option works there
01:22:17 <Guest21> is cabal.project.local declaration different from passing it as arguments? (cabal.project.local)
01:22:33 <Guest21> (https://paste.tomsmeding.com/X27wQMlq)*
01:22:38 <Guest21> https://paste.tomsmeding.com/X27wQMlq
01:22:48 <geekosaur> yes, because it allows specifying them per dependency
01:22:54 yosef` joins (~yosef`@user/yosef/x-2947716)
01:23:25 <geekosaur> whereas (v2-)install has no idea what to do aside from applying them to the current package, not its dependencies
01:25:26 <geekosaur> (you should probably read up on https://cabal.readthedocs.io/en/3.8/nix-local-build-overview.html#nix-style-local-builds to understand what's up with v2-install)
01:28:24 <geekosaur> unfortunately cases like this suggest a need for a cabal.project.global that could be used any time readline or similar libraries were needed as a dependency, but that doesn't currently exist
01:33:54 <Guest21> is there a way to successfully v2-install readline globally?
01:34:40 <geekosaur> I think you'll have to ask in #hackage, but I suspect this is one of those cases where v2-commands don't quite do what you need yet
01:35:05 <geekosaur> sclv might know more if they'[re around
01:37:45 <Guest21> i see, i'll keep chiseling away at this topic, thanks a lot for monumental help
01:38:44 <EvanR> installing stuff globally is what used to cause cabal hell right, and now we have sandboxing which is avoids it?
01:39:51 <geekosaur> yes, but sometimes it's a bit too sandboxed
01:40:26 <geekosaur> everything that uses readline needs a cabal.project.local that tells its readline dependency how to build
01:40:41 × Jackneill quits (~Jackneill@20014C4E1E1AA2006F74B99BA9A50702.dsl.pool.telekom.hu) (Ping timeout: 260 seconds)
01:40:54 <geekosaur> a cabal.project.global that sat next to (or within) the global cabal config would ameliorate this
01:43:58 <Guest21> to add some context why i wanted to do it globally. i tried compiling jhc (i know editline is sufficient, but i wanted to understand why passing readline location arguments failed), which i think expected global installations of packages and it was this that made me want to learn how global installations work
01:44:19 × machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 246 seconds)
01:46:15 bitdex joins (~bitdex@gateway/tor-sasl/bitdex)
01:46:30 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
01:48:01 × Guest21 quits (~Guest21@178.255.149.181) (Quit: Client closed)
01:51:25 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 260 seconds)
01:54:05 × xff0x quits (~xff0x@2405:6580:b080:900:6c8e:2e92:196f:e24b) (Ping timeout: 240 seconds)
02:00:16 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
02:00:53 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
02:01:03 × jathan quits (~jathan@69.61.93.38) (Quit: WeeChat 2.3)
02:02:41 × pointlessslippe1 quits (~pointless@212.82.82.3) (Ping timeout: 240 seconds)
02:05:38 × yosef` quits (~yosef`@user/yosef/x-2947716) (Ping timeout: 250 seconds)
02:08:34 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
02:11:06 pointlessslippe1 joins (~pointless@212.82.82.3)
02:12:29 × otto_s quits (~user@p5de2f612.dip0.t-ipconnect.de) (Ping timeout: 240 seconds)
02:14:23 otto_s joins (~user@p5b044a1d.dip0.t-ipconnect.de)
02:15:52 × emmanuelux quits (~emmanuelu@user/emmanuelux) (Quit: au revoir)
02:19:22 × jocke-l quits (jocke-l@a.x0.is) (Server closed connection)
02:19:47 jocke-l joins (jocke-l@a.x0.is)
02:32:00 × vilya quits (~vilya@user/vilya) (Ping timeout: 245 seconds)
02:32:07 vilya_ joins (~vilya@user/vilya)
02:36:01 × ystael quits (~ystael@user/ystael) (Ping timeout: 240 seconds)
02:36:35 × thegeekinside quits (~thegeekin@189.141.80.123) (Remote host closed the connection)
02:37:51 × pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Ping timeout: 245 seconds)
02:38:22 erty` joins (~user@122.161.49.213)
02:39:18 × notzmv quits (~zmv@user/notzmv) (Ping timeout: 256 seconds)
02:39:28 xff0x joins (~xff0x@125x103x176x34.ap125.ftth.ucom.ne.jp)
02:39:55 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Ping timeout: 245 seconds)
02:40:02 × erty quits (~user@user/aeroplane) (Ping timeout: 252 seconds)
02:46:52 × chexum quits (~quassel@gateway/tor-sasl/chexum) (Ping timeout: 264 seconds)
02:50:39 yosef` joins (~yosef`@user/yosef/x-2947716)
02:58:00 × euleritian quits (~euleritia@dynamic-089-204-135-248.89.204.135.pool.telefonica.de) (Read error: Connection reset by peer)
02:58:18 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
03:09:46 × edr quits (~edr@user/edr) (Quit: Leaving)
03:11:30 notzmv joins (~zmv@user/notzmv)
03:15:42 chexum joins (~quassel@gateway/tor-sasl/chexum)
03:16:50 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
03:18:41 × td_ quits (~td@i53870929.versanet.de) (Ping timeout: 245 seconds)
03:19:23 kiriakos joins (~kiriakos@p57b6414b.dip0.t-ipconnect.de)
03:20:29 td_ joins (~td@i53870918.versanet.de)
03:21:17 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
03:34:54 × yosef` quits (~yosef`@user/yosef/x-2947716) (Ping timeout: 250 seconds)
03:34:58 × bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
03:34:59 × She quits (haveident@libera/staff/she/her) (*.net *.split)
03:34:59 × bastelfreak quits (bastelfrea@libera/staff/VoxPupuli.bastelfreak) (*.net *.split)
03:35:10 She joins (haveident@libera/staff/she/her)
03:35:21 bastelfreak joins (bastelfrea@libera/staff/VoxPupuli.bastelfreak)
03:35:54 bitdex joins (~bitdex@gateway/tor-sasl/bitdex)
03:48:19 erty` parts (~user@122.161.49.213) (ERC 5.4 (IRC client for GNU Emacs 28.2))
03:51:01 × larnee quits (~gm@APN-123-251-154-gprs.simobil.net) (Quit: larnee)
03:52:10 telser joins (~quassel@user/telser)
03:59:01 finn_elija joins (~finn_elij@user/finn-elija/x-0085643)
03:59:01 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Killed (NickServ (Forcing logout FinnElija -> finn_elija)))
03:59:01 finn_elija is now known as FinnElija
03:59:31 × erisco quits (~erisco@d24-141-66-165.home.cgocable.net) (Quit: ZNC 1.8.2+cygwin2 - https://znc.in)
04:00:34 erisco joins (~erisco@d24-141-66-165.home.cgocable.net)
04:00:48 vilya_ is now known as vilya
04:07:55 × superbil quits (~superbil@1-34-176-171.hinet-ip.hinet.net) (*.net *.split)
04:08:24 superbil joins (~superbil@1-34-176-171.hinet-ip.hinet.net)
04:09:04 × friendshipaka quits (~Friendshi@user/Friendship) (Read error: Connection reset by peer)
04:09:31 × ddellacosta quits (~ddellacos@ool-44c738de.dyn.optonline.net) (Ping timeout: 245 seconds)
04:09:39 × cstml quits (~pi@user/cstml) (Read error: Connection reset by peer)
04:10:44 ddellacosta joins (~ddellacos@ool-44c738de.dyn.optonline.net)
04:10:54 × aforemny quits (~aforemny@i59F516FE.versanet.de) (Ping timeout: 268 seconds)
04:11:11 aforemny joins (~aforemny@2001:9e8:6cf2:3800:48da:c417:67b:551b)
04:13:13 Inst joins (~Inst@120.244.192.250)
04:18:18 × notzmv quits (~zmv@user/notzmv) (Ping timeout: 268 seconds)
04:19:06 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 245 seconds)
04:37:10 × ddellacosta quits (~ddellacos@ool-44c738de.dyn.optonline.net) (Ping timeout: 256 seconds)
04:37:56 × pavonia quits (~user@user/siracusa) (Quit: Bye!)
04:38:56 ddellacosta joins (~ddellacos@ool-44c738de.dyn.optonline.net)
04:47:24 × xsarnik quits (xsarnik@lounge.fi.muni.cz) (Server closed connection)
04:47:40 xsarnik joins (xsarnik@lounge.fi.muni.cz)
04:49:35 qqq joins (~qqq@92.43.167.61)
04:54:21 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
04:54:53 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
05:04:55 rosco joins (~rosco@175.136.157.149)
05:05:26 derpyxdhs joins (~Thunderbi@user/derpyxdhs)
05:10:39 × acarrico quits (~acarrico@dhcp-68-142-49-163.greenmountainaccess.net) (Server closed connection)
05:11:50 acarrico joins (~acarrico@dhcp-68-142-49-163.greenmountainaccess.net)
05:24:34 × derpyxdhs quits (~Thunderbi@user/derpyxdhs) (Quit: derpyxdhs)
05:28:52 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Ping timeout: 264 seconds)
05:31:17 trev joins (~trev@user/trev)
05:31:23 jinsun_ joins (~jinsun@user/jinsun)
05:31:23 × jinsun quits (~jinsun@user/jinsun) (Killed (silver.libera.chat (Nickname regained by services)))
05:31:24 jinsun_ is now known as jinsun
05:31:43 biberu joins (~biberu@user/biberu)
05:36:31 jinsun_ joins (~jinsun@user/jinsun)
05:36:31 jinsun is now known as Guest5766
05:36:32 jinsun_ is now known as jinsun
05:36:46 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
05:40:37 × Guest5766 quits (~jinsun@user/jinsun) (Ping timeout: 268 seconds)
05:41:44 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
05:42:09 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
05:45:52 × Unicorn_Princess quits (~Unicorn_P@user/Unicorn-Princess/x-3540542) (Remote host closed the connection)
05:49:17 thegeekinside joins (~thegeekin@189.141.80.123)
05:52:30 × jinsun quits (~jinsun@user/jinsun) (Read error: Connection reset by peer)
05:56:38 jinsun joins (~jinsun@user/jinsun)
05:59:41 × telser quits (~quassel@user/telser) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.)
06:05:36 _ht joins (~Thunderbi@28-52-174-82.ftth.glasoperator.nl)
06:13:39 × Inst quits (~Inst@120.244.192.250) (Ping timeout: 246 seconds)
06:14:07 × Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer)
06:15:07 Sgeo joins (~Sgeo@user/sgeo)
06:15:43 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
06:17:50 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 252 seconds)
06:17:54 takuan joins (~takuan@178-116-218-225.access.telenet.be)
06:17:58 euleritian joins (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de)
06:19:07 seeg123456 joins (~seeg12345@64.176.64.83)
06:19:30 × euleritian quits (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de) (Read error: Connection reset by peer)
06:19:46 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
06:19:57 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 246 seconds)
06:27:15 acidjnk joins (~acidjnk@p200300d6e72b9310fd221caae09ed082.dip0.t-ipconnect.de)
06:27:23 notzmv joins (~zmv@user/notzmv)
06:28:48 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 256 seconds)
06:29:07 euleritian joins (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de)
06:33:37 × Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer)
06:33:56 × kmein quits (~weechat@user/kmein) (Server closed connection)
06:34:06 Sgeo joins (~Sgeo@user/sgeo)
06:34:21 kmein joins (~weechat@user/kmein)
06:35:03 Inst joins (~Inst@120.244.192.250)
06:47:38 × thegeekinside quits (~thegeekin@189.141.80.123) (Remote host closed the connection)
06:51:50 michalz joins (~michalz@185.246.207.193)
06:56:00 × kiriakos quits (~kiriakos@p57b6414b.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
06:56:58 lisbeths joins (uid135845@id-135845.lymington.irccloud.com)
07:08:48 × [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Read error: Connection reset by peer)
07:09:16 misterfish joins (~misterfis@84-53-85-146.bbserv.nl)
07:09:27 thegeekinside joins (~thegeekin@189.141.80.123)
07:10:21 sord937 joins (~sord937@gateway/tor-sasl/sord937)
07:11:53 × rosco quits (~rosco@175.136.157.149) (Ping timeout: 268 seconds)
07:12:06 × Sgeo quits (~Sgeo@user/sgeo) (Ping timeout: 246 seconds)
07:16:28 <Inst> http://page.mi.fu-berlin.de/prechelt/Biblio/jccpprtTR.pdf
07:16:30 <Inst> wat
07:17:15 <Inst> check section 4, takes py and perl 2 hours to do this
07:17:19 <Inst> on average
07:17:48 <Inst> sequence . fmap (toList) . show
07:18:05 <Inst> if you don't care about performance, this is so easy
07:18:15 <Inst> 30 minutes in Haskell, and I suck
07:20:56 × thegeekinside quits (~thegeekin@189.141.80.123) (Ping timeout: 256 seconds)
07:27:41 yosef` joins (~yosef`@user/yosef/x-2947716)
07:29:08 Sgeo joins (~Sgeo@user/sgeo)
07:31:23 <mauke> perl 5.003? oh, baby
07:31:42 <mauke> that's 1996
07:37:34 × yosef` quits (~yosef`@user/yosef/x-2947716) (Ping timeout: 250 seconds)
07:37:40 × euleritian quits (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de) (Read error: Connection reset by peer)
07:37:57 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
07:46:07 fendor joins (~fendor@2a02:8388:1640:be00:ca17:ceee:5bbe:1594)
07:47:15 _73_ joins (~anon_73@2600:4040:5205:d800:21e8:9777:49a5:db28)
07:47:51 × _73 quits (~anon_73@2600:4040:5205:d800:21e8:9777:49a5:db28) (Ping timeout: 245 seconds)
07:52:01 × waleee quits (~waleee@h-176-10-144-38.NA.cust.bahnhof.se) (Ping timeout: 245 seconds)
08:00:40 chomwitt joins (~chomwitt@2a02:587:7a1f:e00:1ac0:4dff:fedb:a3f1)
08:02:23 vpan joins (~vpan@mail.elitnet.lt)
08:05:47 <Inst> lol you're kidding me
08:05:54 <Inst> subsequences probably isn't what's wanted
08:06:39 <Inst> filter isInDict . fmap (subsequences =<<) . sequence . fmap (toListOfChars) . show
08:10:59 <ski> what is this `toList'/`toListOfChars', that you're passing `Char's into it ?
08:12:01 <Inst> i mean the problem of the paper
08:12:06 <Inst> look up all possible words from a given telephone number
08:12:51 <ski> mhm, okay
08:13:09 <ski> @src mapM
08:13:10 <lambdabot> mapM f as = sequence (map f as)
08:13:13 <Inst> ah
08:13:16 <Inst> whoos
08:13:18 <Inst> whoops
08:13:36 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
08:13:37 <ski> so `sequence . fmap blah' is `mapM blah'
08:13:58 <Inst> so just traverse (toListOfChars) . show
08:14:08 <ski> or `traverse' sure
08:14:14 <Inst> I just find it funny because it's almost a one-liner in Haskell, but performance will suffer
08:14:30 × stiell quits (~stiell@gateway/tor-sasl/stiell) (Remote host closed the connection)
08:14:55 idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c)
08:14:56 stiell joins (~stiell@gateway/tor-sasl/stiell)
08:17:36 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 256 seconds)
08:18:20 euleritian joins (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de)
08:19:29 lortabac joins (~lorenzo@2a01:e0a:541:b8f0:93f2:661e:d61:f6f4)
08:22:11 cstml joins (~cstml@user/cstml)
08:28:18 × FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Quit: FinnElija)
08:32:02 × Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer)
08:35:45 rosco joins (~rosco@175.136.157.149)
08:41:12 Lord_of_Life_ joins (~Lord@user/lord-of-life/x-2819915)
08:42:14 × Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 268 seconds)
08:42:14 zetef joins (~quassel@95.77.17.251)
08:42:37 Lord_of_Life_ is now known as Lord_of_Life
08:42:56 × tzh quits (~tzh@c-71-193-181-0.hsd1.or.comcast.net) (Quit: zzz)
08:44:39 × euleritian quits (~euleritia@dynamic-089-204-130-178.89.204.130.pool.telefonica.de) (Read error: Connection reset by peer)
08:44:56 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
08:54:09 machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net)
09:03:22 × fendor quits (~fendor@2a02:8388:1640:be00:ca17:ceee:5bbe:1594) (Remote host closed the connection)
09:04:12 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
09:04:17 × benjaminl quits (~benjaminl@user/benjaminl) (Server closed connection)
09:04:33 benjaminl joins (~benjaminl@user/benjaminl)
09:10:07 × Buggys quits (Buggys@Buggy.shelltalk.net) (Ping timeout: 264 seconds)
09:10:29 × lawt quits (~lawt@129.159.36.129) (Server closed connection)
09:10:53 lawt joins (~lawt@2603:c024:c008:d000:5b4f:1ef2:fed2:ef3d)
09:15:23 FinnElija joins (~finn_elij@user/finn-elija/x-0085643)
09:17:32 × sclv quits (sid39734@haskell/developer/sclv) (Server closed connection)
09:17:44 sclv joins (sid39734@haskell/developer/sclv)
09:20:12 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 246 seconds)
09:22:11 Buggys joins (Buggys@Buggy.shelltalk.net)
09:24:16 mechap joins (~mechap@user/mechap)
09:27:11 × integral quits (sid296274@user/integral) (Server closed connection)
09:27:26 integral joins (sid296274@user/integral)
09:27:48 Jackneill joins (~Jackneill@20014C4E1E1AA200CF385604A8335158.dsl.pool.telekom.hu)
09:33:37 × snek quits (sid280155@id-280155.lymington.irccloud.com) (Server closed connection)
09:33:48 snek joins (sid280155@id-280155.lymington.irccloud.com)
09:34:27 × santiagopim quits (~user@90.167.66.131) (Remote host closed the connection)
09:34:48 CiaoSen joins (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5)
09:36:50 × iphy quits (sid67735@id-67735.lymington.irccloud.com) (Server closed connection)
09:37:00 iphy joins (sid67735@id-67735.lymington.irccloud.com)
09:40:00 chele joins (~chele@user/chele)
09:40:42 zetef joins (~quassel@95.77.17.251)
09:44:21 fendor joins (~fendor@2a02:8388:1640:be00:2528:5dc7:a36e:9b87)
09:47:00 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Remote host closed the connection)
09:48:12 <dminuoso> Dense code is rarely also performant.
09:48:46 × econo_ quits (uid147250@id-147250.tinside.irccloud.com) (Quit: Connection closed for inactivity)
09:51:25 <dminuoso> There's some strange bits in that PDF
09:51:30 <dminuoso> "Please do not over-optimize your program. Deliver your first reasonable solution."
09:51:50 <dminuoso> Those are some two contradicting extremes.
09:52:25 alp_ joins (~alp@2001:861:5e02:eff0:acc6:6062:8e53:293f)
09:53:12 <dminuoso> But yeah, if you just use subsequences and `filter`, you are not going to be happy.
09:53:20 <dminuoso> It's just not a *reasonable* solution.
09:54:24 coot joins (~coot@89-69-206-216.dynamic.chello.pl)
09:57:07 × hsw_ quits (~hsw@2001-b030-2303-0104-0172-0025-0012-0132.hinet-ip6.hinet.net) (Quit: Leaving)
09:57:24 hsw joins (~hsw@2001-b030-2303-0104-0172-0025-0012-0132.hinet-ip6.hinet.net)
10:04:55 puke joins (~puke@user/puke)
10:05:35 mc47 joins (~mc47@xmonad/TheMC47)
10:08:28 danse-nr3 joins (~danse@151.43.223.187)
10:15:21 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
10:17:35 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
10:18:14 kiriakos joins (~kiriakos@p57b647b8.dip0.t-ipconnect.de)
10:19:33 Square2 joins (~Square4@user/square)
10:21:38 <Square2> Are there any publicly available applauded applications of GADTs. Ie, not just a tutorial but some production ready app/lib usage.
10:23:03 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 268 seconds)
10:24:24 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
10:24:45 × xff0x quits (~xff0x@125x103x176x34.ap125.ftth.ucom.ne.jp) (Ping timeout: 260 seconds)
10:26:48 gehmehgeh joins (~user@user/gehmehgeh)
10:33:52 × danse-nr3 quits (~danse@151.43.223.187) (Read error: Connection reset by peer)
10:34:00 danse-nr3 joins (~danse@151.43.223.187)
10:35:00 Pickchea joins (~private@user/pickchea)
10:40:05 <Inst> i think the specification wants this:
10:40:07 <Inst> phoneSub [] = []
10:40:07 <Inst> phoneSub (x:xs) = ((x:) <$> inits xs) <> phoneSub xs
10:40:19 <Inst> which annoys me because I keep on thinking there's probably a more performant way to write this using scanl' etc
10:40:39 <Inst> oh, i'm a freaking idiot, again
10:41:03 <Inst> tails =<< inits foo
10:51:54 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 246 seconds)
10:52:36 × mechap quits (~mechap@user/mechap) (Ping timeout: 246 seconds)
10:54:40 × califax quits (~califax@user/califx) (Ping timeout: 264 seconds)
10:54:45 califax_ joins (~califax@user/califx)
10:55:27 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Read error: Connection reset by peer)
10:56:02 califax_ is now known as califax
10:57:37 coot_ joins (~coot@89-69-206-216.dynamic.chello.pl)
10:57:54 × ft quits (~ft@p508db3bc.dip0.t-ipconnect.de) (Quit: leaving)
10:57:57 <Inst> or rather concatMap (tail . inits) . tail . inits
10:58:32 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Ping timeout: 256 seconds)
10:58:37 coot_ is now known as coot
11:06:13 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Ping timeout: 268 seconds)
11:06:28 <bwe> how can I let the (Scalpel) parser return `Either Text a` instead of `a`? https://gist.github.com/benjaminweb/a85b8713790dc0b0d08702406d01dc51
11:07:09 × [exa] quits (~exa@user/exa/x-3587197) (Server closed connection)
11:07:18 [exa] joins (~exa@srv3n.blesmrt.net)
11:08:55 <ncf> use the Alternative instance?
11:11:35 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)
11:12:39 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Ping timeout: 260 seconds)
11:13:15 × CiaoSen quits (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5) (Ping timeout: 245 seconds)
11:13:18 xff0x joins (~xff0x@2405:6580:b080:900:3141:d1c2:46a9:b11c)
11:13:42 <bwe> ncf: How?
11:13:59 × Pickchea quits (~private@user/pickchea) (Quit: Leaving)
11:14:37 × Jackneill quits (~Jackneill@20014C4E1E1AA200CF385604A8335158.dsl.pool.telekom.hu) (Remote host closed the connection)
11:16:53 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
11:19:08 × tritlo_ quits (sid58727@id-58727.hampstead.irccloud.com) (Server closed connection)
11:19:21 tritlo_ joins (sid58727@id-58727.hampstead.irccloud.com)
11:20:30 <ncf> Right <$> text ... <|> pure (Left "no")
11:22:06 <danse-nr3> interesting
11:22:06 <danse-nr3> % :t \f a b c -> f <$> a <|> b <|> c
11:22:06 <yahb2> <interactive>:1:21: error: ; • Variable not in scope: (<|>) :: f b -> t -> t0 ; • Perhaps you meant one of these: ; ‘<*>’ (imported from Prelude), ‘<>’ (imported from Prelude), ; ...
11:22:16 <danse-nr3> import Data.Applicative
11:22:21 <danse-nr3> % import Data.Applicative
11:22:21 <yahb2> <no location info>: error: ; Could not find module ‘Data.Applicative’ ; It is not a module in the current program, or in any known package.
11:22:26 <danse-nr3> % import Control.Applicative
11:22:26 <yahb2> <no output>
11:22:30 <danse-nr3> % :t \f a b c -> f <$> a <|> b <|> c
11:22:30 <yahb2> \f a b c -> f <$> a <|> b <|> c ; :: Alternative f => (a1 -> a2) -> f a1 -> f a2 -> f a2 -> f a2
11:23:15 <danse-nr3> not sure about the role of that `Right` at the beginning, seems unnecessary
11:23:28 × Inst quits (~Inst@120.244.192.250) (Ping timeout: 256 seconds)
11:24:09 <ncf> well they wanted an Either
11:25:08 <danse-nr3> like `Right text <|> Left "no"`?
11:25:31 <ncf> text is a scraper
11:25:41 <danse-nr3> oh makes sense, thanks
11:26:30 <bwe> I get the idea but what's needed to get the implementation compile? https://gist.github.com/benjaminweb/a85b8713790dc0b0d08702406d01dc51
11:27:46 <ncf> In the expression: pure Left "no"
11:29:20 <bwe> pure $ Left "no" -- compiles
11:30:18 <bwe> (Right <$> text ( "span" @: [hasClass "author"])) <|> pure $ Left "no" -- doesn't
11:30:24 × jackdk quits (sid373013@cssa/jackdk) (Server closed connection)
11:30:33 Unicorn_Princess joins (~Unicorn_P@user/Unicorn-Princess/x-3540542)
11:30:36 jackdk joins (sid373013@cssa/jackdk)
11:30:39 <ncf> $ has the lowest precedence
11:30:40 <bwe> (Right <$> text ( "span" @: [hasClass "author"])) <|> (pure $ Left "no") -- compiles
11:31:24 <bwe> yeah, could be simplified in parentheses terms, but it compiles at least
11:31:44 <bwe> ncf: kudos for the obvious solution I overlooked!
11:31:57 × ProofTechnique_ quits (sid79547@id-79547.ilkley.irccloud.com) (Server closed connection)
11:32:13 ProofTechnique_ joins (sid79547@id-79547.ilkley.irccloud.com)
11:34:21 pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655)
11:36:36 × JSharp quits (sid4580@id-4580.lymington.irccloud.com) (Server closed connection)
11:36:53 JSharp joins (sid4580@id-4580.lymington.irccloud.com)
11:37:56 <bwe> https://gist.github.com/benjaminweb/a85b8713790dc0b0d08702406d01dc51 -- rev 3
11:39:07 <bwe> how can I combine multiple `Scraper String (Either String String)` in a `combinedScraper` that fails and returns on the first `Left` produced by a sub scraper? I've added a blueprint of combinedScraper to the gist ^.
11:40:28 × chomwitt quits (~chomwitt@2a02:587:7a1f:e00:1ac0:4dff:fedb:a3f1) (Ping timeout: 256 seconds)
11:45:00 × vpan quits (~vpan@mail.elitnet.lt) (Ping timeout: 256 seconds)
11:46:06 × cstml quits (~cstml@user/cstml) (Quit: WeeChat 2.3)
11:46:21 cstml joins (~cstml@user/cstml)
11:47:31 <dminuoso> I have a list of numbers [1,2,3,6,8,9,10] and I would like to work with all subsequent pairs. I dont care about the behavior on the edges (wrap around, drop one element), anything is fine here
11:48:05 <dminuoso> i.e. something like [1,2,6,7] -> [(1,2), (2,6), (6, 7)]
11:48:13 <stefan-__> zip xs (tail xs) ?
11:48:25 <ncf> > zip <$> id <*> tail $ [1,2,6,7]
11:48:27 <lambdabot> [(1,2),(2,6),(6,7)]
11:48:28 <dminuoso> Oh yes, works for me. :)
11:48:33 <dminuoso> Thanks, stefan-__.
11:48:38 <stefan-__> yw :)
11:49:08 <[Leary]> @quote aztec.god
11:49:08 <lambdabot> quicksilver says: zip`ap`tail - the Aztec god of consecutive numbers
11:49:59 <ncf> haha
11:52:15 <ncf> bwe: maybe you want ScraperT Either?
11:52:51 <ncf> (or ExceptT Scalpel)
11:53:05 sawilagar joins (~sawilagar@user/sawilagar)
11:53:11 <bwe> ncf: I feel so but haven't had any experience with Monad transformers yet. Is that a case for monad transformers?
11:53:24 <ncf> T is for transformer yes
11:54:00 <cstml> > mconcat $ (const "ha") <$> [1..3]
11:54:02 <lambdabot> "hahaha"
11:55:38 <cstml> > :t mconcat $ (const "ha") <$> [1..3]
11:55:39 <lambdabot> <hint>:1:1: error: parse error on input ‘:’
11:55:48 × mauke quits (~mauke@user/mauke) (Ping timeout: 240 seconds)
11:56:09 <bwe> ncf: what's the easiest way you could recommend to grasp Monad transformers?
11:56:45 <ncf> use them
11:56:52 mauke joins (~mauke@user/mauke)
11:57:15 mechap joins (~mechap@user/mechap)
11:57:55 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Remote host closed the connection)
11:58:39 <dminuoso> bwe: Invent them.
11:58:40 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
11:58:42 chomwitt joins (~chomwitt@ppp-94-67-217-242.home.otenet.gr)
11:59:15 <bwe> so, I understand them to connect two worlds, let's say contexts, is that right?
11:59:30 <dminuoso> bwe: Its best not to describe them in vague terms.
11:59:41 <cstml> bwe: use IdentityT. Then stack it. Then look at what it does. Then look at the code.
11:59:47 <dminuoso> Imagine a highly sophisticiated mathematician explaining stuff in abstract terms to a beginner.
11:59:50 <dminuoso> It just wont connect.
12:00:43 <dminuoso> The vague terms make sense for those that have achieved higher levels of understanding, but they are not good vehicles for learning
12:01:23 <bwe> dminuoso: You're right, I should go bottom-up, like cstml suggests.
12:02:00 <cstml> bwe: It helps understanding the trivial case, then taking that understanding and expanding.
12:02:11 juri__ joins (~juri@79.140.117.145)
12:02:50 <dminuoso> bwe: But the short intuition is really simple. `State` lets you do stateful computations, and `Either` lets you do computations with exceptions.
12:02:59 <dminuoso> Wouldn't it be great to have computations with both state and exceptions?
12:03:13 × juri_ quits (~juri@84-19-175-187.pool.ovpn.com) (Ping timeout: 258 seconds)
12:03:18 <dminuoso> So that's the motivation that starts all of this.
12:04:18 <cstml> dminuoso: Both state and exceptions, or both exceptions and state?
12:04:26 <dminuoso> cstml: :)
12:04:36 <dminuoso> Ill leave that distinction as a lesson for another day.
12:04:49 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
12:04:50 <cstml> dminuoso: exercise left for the reader.
12:04:53 <dminuoso> Sure
12:04:55 <cstml> or ReaderT
12:04:57 × juri__ quits (~juri@79.140.117.145) (Read error: Connection reset by peer)
12:05:21 <dminuoso> I think State and Either T/Maybe are better learning vehicles, because their effects are much more intuitive and obvious
12:06:51 Inst joins (~Inst@120.244.192.250)
12:07:11 juri_ joins (~juri@84-19-175-187.pool.ovpn.com)
12:10:33 tremon joins (~tremon@83.80.159.219)
12:10:51 actioninja7 joins (~actioninj@user/actioninja)
12:11:57 <bwe> cstml: How can I go a step back from that trivial case? I am struggling to define the working base case of IdentityT.
12:12:28 × actioninja quits (~actioninj@user/actioninja) (Ping timeout: 255 seconds)
12:12:28 actioninja7 is now known as actioninja
12:13:55 larnee joins (~gm@APN-123-243-222-gprs.simobil.net)
12:14:36 <cstml> bwe: have a look on hackage https://hackage.haskell.org/package/transformers-0.6.1.1/docs/src/Control.Monad.Trans.Identity.html#IdentityT
12:15:52 <bwe> it's basically a wrapper but what does it wrap?
12:20:23 Jackneill joins (~Jackneill@20014C4E1E1AA200D010BAADCC2D344F.dsl.pool.telekom.hu)
12:20:26 <dminuoso> bwe: rather than thinking about IdentityT, I would start by just handrolling State.
12:20:40 <dminuoso> And once you have done that, handroll Maybe. And once you have done that, write a custom monad that does both.
12:20:57 <dminuoso> The first transformer you would conceive is just a generalization of that custom monad.
12:24:03 <dminuoso> And the approach to do that, is after you have done state + maybe, start doing reader + maybe. And then perhaps IO + maybe. A pattern will emerge, and if you codify it, it will be named MaybeT.
12:24:49 × pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Quit: WeeChat 3.5)
12:24:51 <dminuoso> The motivation doesnt even become clear until you have realized that writing a custom newtype, slapping `Maybe` in the right spot every time, becomes cumbersome and silly - because it will always go into a particular spot.
12:25:04 <dminuoso> And the Monad instances will be mechanical
12:32:21 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Ping timeout: 246 seconds)
12:32:36 × larnee quits (~gm@APN-123-243-222-gprs.simobil.net) (Quit: larnee)
12:34:18 × danse-nr3 quits (~danse@151.43.223.187) (Ping timeout: 256 seconds)
12:34:59 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
12:36:05 vpan joins (~vpan@mail.elitnet.lt)
12:36:13 × vpan quits (~vpan@mail.elitnet.lt) (Client Quit)
12:36:22 vpan joins (~vpan@mail.elitnet.lt)
12:36:29 vpan is now known as Guest5869
12:36:38 × eso quits (a0662dfd5e@2604:bf00:561:2000::1266) (Server closed connection)
12:36:49 eso joins (a0662dfd5e@2604:bf00:561:2000::1266)
12:37:01 edr joins (~edr@user/edr)
12:37:41 Guest5869 is now known as vpan
12:38:11 × chessai quits (sid225296@id-225296.lymington.irccloud.com) (Server closed connection)
12:38:20 chessai joins (sid225296@id-225296.lymington.irccloud.com)
12:41:06 larnee joins (~gm@APN-123-243-222-gprs.simobil.net)
12:43:56 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Ping timeout: 256 seconds)
12:44:18 danse-nr3 joins (~danse@151.43.223.187)
12:46:37 × xerox quits (~edi@user/edi) (Server closed connection)
12:46:46 xerox joins (~edi@user/edi)
12:50:09 × larnee quits (~gm@APN-123-243-222-gprs.simobil.net) (Remote host closed the connection)
12:53:35 ialwaysC joins (~ialwaysC@2409:40e5:2:da77:8000::)
12:55:37 × ialwaysC quits (~ialwaysC@2409:40e5:2:da77:8000::) (Read error: Connection reset by peer)
12:55:49 × _73_ quits (~anon_73@2600:4040:5205:d800:21e8:9777:49a5:db28) (Quit: Leaving)
12:56:03 _73_ joins (~anon_73@2600:4040:5205:d800:21e8:9777:49a5:db28)
13:02:46 × mechap quits (~mechap@user/mechap) (Ping timeout: 268 seconds)
13:04:08 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
13:06:00 falafel_ joins (~falafel@62.175.113.194.dyn.user.ono.com)
13:09:15 × alp_ quits (~alp@2001:861:5e02:eff0:acc6:6062:8e53:293f) (Ping timeout: 268 seconds)
13:09:21 mechap joins (~mechap@user/mechap)
13:11:22 × _73_ quits (~anon_73@2600:4040:5205:d800:21e8:9777:49a5:db28) (Quit: Leaving)
13:12:21 × noctuks quits (HNnDKbX6rY@user/noctux) (Server closed connection)
13:12:38 × danse-nr3 quits (~danse@151.43.223.187) (Ping timeout: 268 seconds)
13:12:41 noctuks joins (ccm7rRIFr2@user/noctux)
13:12:50 × falafel_ quits (~falafel@62.175.113.194.dyn.user.ono.com) (Ping timeout: 256 seconds)
13:17:14 danse-nr3 joins (~danse@151.43.223.187)
13:18:43 × danse-nr3 quits (~danse@151.43.223.187) (Remote host closed the connection)
13:19:07 danse-nr3 joins (~danse@151.43.223.187)
13:19:36 × juri_ quits (~juri@84-19-175-187.pool.ovpn.com) (Ping timeout: 246 seconds)
13:20:09 juri_ joins (~juri@79.140.117.145)
13:20:46 × xff0x quits (~xff0x@2405:6580:b080:900:3141:d1c2:46a9:b11c) (Ping timeout: 256 seconds)
13:21:41 × juri_ quits (~juri@79.140.117.145) (Read error: Connection reset by peer)
13:22:37 xff0x joins (~xff0x@178.255.149.135)
13:23:48 × danse-nr3 quits (~danse@151.43.223.187) (Ping timeout: 246 seconds)
13:24:22 pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655)
13:24:39 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Remote host closed the connection)
13:25:10 juri_ joins (~juri@84-19-175-187.pool.ovpn.com)
13:26:17 danse-nr3 joins (~danse@151.43.223.187)
13:28:46 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
13:31:51 × xff0x quits (~xff0x@178.255.149.135) (Ping timeout: 246 seconds)
13:31:54 × danse-nr3 quits (~danse@151.43.223.187) (Read error: Connection reset by peer)
13:32:34 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Remote host closed the connection)
13:32:39 danse-nr3 joins (~danse@151.57.219.68)
13:32:58 dcoutts joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
13:33:23 CiaoSen joins (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5)
13:33:55 xff0x joins (~xff0x@2405:6580:b080:900:3141:d1c2:46a9:b11c)
13:34:24 × wagle quits (~wagle@quassel.wagle.io) (Server closed connection)
13:34:40 wagle joins (~wagle@quassel.wagle.io)
13:35:30 × elkcl quits (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru) (Ping timeout: 256 seconds)
13:36:16 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
13:36:23 × jmdaemon quits (~jmdaemon@user/jmdaemon) (Ping timeout: 268 seconds)
13:40:58 elkcl joins (~elkcl@broadband-95-84-226-240.ip.moscow.rt.ru)
13:48:24 × idgaen quits (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) (Quit: WeeChat 4.1.1)
13:50:52 <bwe> dminuoso: building blocks in place: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4
13:51:50 <dminuoso> You have a rather curious indention style
13:52:35 <bwe> dminuoso: inconsistent, right?
13:53:15 <dminuoso> Hold on. What just happened. I alt tabbed, and suddenly it looks all different now.
13:55:01 <bwe> dminuoso: now, writing a custom monad that does both... I would start with a type signature that carries Maybee and State, right? How does that look like? I've no clue here.
13:55:45 <dminuoso> bwe: So its all a bit adhoc, I would now start writing some examples using those monads.
13:56:11 <dminuoso> Some stateful computation that may fail.
14:04:13 × Jackneill quits (~Jackneill@20014C4E1E1AA200D010BAADCC2D344F.dsl.pool.telekom.hu) (Remote host closed the connection)
14:06:30 Jackneill joins (~Jackneill@20014C4E1E1AA200A8C1C5D762EA8C40.dsl.pool.telekom.hu)
14:10:23 alp_ joins (~alp@2001:861:5e02:eff0:e086:39d1:f48d:94d6)
14:11:13 × notzmv quits (~zmv@user/notzmv) (Ping timeout: 268 seconds)
14:17:01 <ski> bwe : (<*>) (State f) (State g) could be State f <*> State g and ditto for the other definitions of infix operators
14:17:56 <ski> i'd probably use `let'-`in', rather than `let' commands inside a `do' (that's not even monadic here), inside the definition of `>>='
14:18:51 <ski> (and there's really no need to use `case' at the bottom, you could pattern-match in the parameters on the left-hand side of the definition, as with your other definitions)
14:19:05 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
14:19:23 <ski> (personally i'd also prefer seeing `Justt (f x)' over `Justt $ f x')
14:19:46 × zaquest quits (~notzaques@5.130.79.72) (Remote host closed the connection)
14:20:04 <ski> (oh, i guess the strange `do' is also in definition of `<*>')
14:21:22 <ski> right, also the outer brackets in `(State s (a -> b))' are redundant
14:23:22 <bwe> updated: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4
14:23:34 <ski> bwe : "I would start with a type signature that carries Maybee and State, right?" -- i suppose you perhaps actually meant "define a data type for a monad that both carries the ability to propagate state, and to fail", is that right ?
14:24:04 <bwe> I've incorporated ski's input and started to sketch out a login function that takes a state and some input
14:24:10 <bwe> ski: correct
14:24:10 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 268 seconds)
14:24:37 <bwe> I seem not to understand how to use the State I defined in an example application :(
14:24:41 <ski> ah, the brackets in `(Justt f) <*> (Justt x)' are still redundant
14:25:22 <ski> (and `>>=' for `Maybee' can also be defined infix (and you forgot a little something, there))
14:26:40 thegeekinside joins (~thegeekin@189.141.80.123)
14:26:59 <ski> (heh, and did didn't touch `(<*>) (State f) (State g)' (instead `(<*>) (Justt f) (Justt x)', where the same point applied), actually)
14:27:35 pavonia joins (~user@user/siracusa)
14:27:51 benjaminedwardwe joins (~benjamine@ool-45707daf.dyn.optonline.net)
14:28:10 <ski> is `validLogin' supposed to throw away the password ?
14:28:46 <bwe> ski: yes, it's just a dummy
14:28:59 <bwe> but actually, we can propagate it
14:29:24 × Hooloovoo quits (~Hooloovoo@hax0rbana.org) (Ping timeout: 240 seconds)
14:29:46 <ski> ok
14:30:25 <ski> is the `Maybe' in `login' intended to express that your computation could possibly fail ?
14:30:41 <ski> (s/did didn't/you didn't/)
14:31:36 × CiaoSen quits (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5) (Ping timeout: 256 seconds)
14:31:52 <ski> also not quite sure why `login' is taking a state action as an input
14:32:02 <bwe> updated: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4
14:32:47 <bwe> ski: well, I am trying to come up with some example function that is stateful and can fail
14:33:21 <bwe> but not sure here how to approach it - I assume the it takes state as an input, right?
14:33:43 <bwe> or would it just be LoginStatus in my case?
14:33:55 <ski> (still `(>>=) (State g) f' left. obvviously, if you really prefer defining infix operators prefix, you can do so. although it tends to be nice with consistency, unless there's some reason one wants to do it differently in some case)
14:34:40 <ski> "trying to come up with some example function that is stateful and can fail" -- right
14:35:00 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 256 seconds)
14:35:10 <bwe> updated: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4
14:35:51 <ski> "I assume the it takes state as an input, right?" -- `login' will be given an input state (of type `Maybe (String,String)' in your case), *implicitly*, yes. this `s' parameter of yours is not that input state, it's a callback action. that may or may not be reasonable here, i don't know
14:35:52 euleritian joins (~euleritia@x52717980.dyn.telefonica.de)
14:36:49 <ski> perhaps `login' wants to first login, and only then (if that succeeds), run the callback action (and then perhaps do something more after that)
14:37:23 <bwe> I have come up with an unclear function intention.
14:37:30 <ski> or, perhaps instead, whoever is going to call `login' could instead directly perform the code that would have been in the callback, *after* `login' (successfully) finishes (in the case there was nothing more to do after it in `login')
14:38:10 <bwe> which example function would you like me to write instead?
14:38:40 <ski> however, it *looks* like, to me, that the `LoginStatus' that you intend to `case' on in `login' is what your current callback is supposed to give as result, is that so ?
14:38:53 <bwe> "trying to come up with some example function that is stateful and can fail" -- right -- so using Maybee and State
14:40:18 <ski> well .. perhaps it could be more suitable to use `State (String,String) (Maybe LoginStatus)' rather than `State (Maybe (String,String)) LoginStatus'
14:40:39 <ski> "which example function would you like me to write instead?" -- sorry, i'm not quite clear about that (since i'm not quite clear of what's your aim)
14:41:20 <bwe> ski: trying to create a situation where I stumble over the need to write a Monad transformer, so a Monad that handles both Maybee and State!
14:41:51 <ski> i assume you mean, a monad that handles both failure and state-threading/passing
14:42:12 <ski> (do note that you have *not* defined such a monad, yet)
14:42:36 × cods quits (~fred@tuxee.net) (Server closed connection)
14:42:49 cods joins (~fred@tuxee.net)
14:42:54 <bwe> dminuoso: here?
14:43:03 <ski> (but going down alleys and deadends can be quite edifying, too)
14:44:19 <ski> e.g. it's useful to understand the difference between (your current) `State (Maybe (String,String)) LoginStatus', and the `State (String,String) (Maybe LoginStatus)' i mentioned, and the third alternative i just hinted at
14:45:55 <bwe> well, I am trying to understand the concept of State here, still
14:46:23 <bwe> since I don't I mess it up, nor can I conceive a sensible type signature
14:46:37 <ski> anyway .. since you switched from `String' to `(String,String)' in the signature for `login', when you did the same for the (possible) result in `validLogin', i'm presuming that the `(String,String)' (which is in the state that's implicitly carried around) in `login' are supposed to be the user and password, is that right ?
14:47:19 <bwe> ski: and yes, dminuoso asked me to write some stateful function that can fail -- to realise the need to write a custom monad for state and Maybee
14:47:20 × qhong quits (~qhong@DN160vrd000d6kpg009l6c0000fj.stanford.edu) (Read error: Connection reset by peer)
14:47:30 qhong joins (~qhong@rescomp-21-400677.stanford.edu)
14:47:48 × mechap quits (~mechap@user/mechap) (Ping timeout: 246 seconds)
14:48:02 × vilya quits (~vilya@user/vilya) (Ping timeout: 256 seconds)
14:48:15 <ski> yes, it's good advice, to get more concrete, to understand the ramifications of your probably initially rather vaguely grasped monad definitions (vague in how they're to be applied in practice)
14:48:48 <bwe> ski: yes, but again, I first would like to understand the State thing and don't want to waste our time with a badly defined function (due to not understood State)
14:49:05 <ski> well, okay
14:49:17 <bwe> so, why does State carry a result of a function and not only the state?
14:49:41 <ski> i was thinking maybe you already had decided you understood basic `State' (as you've defined it) well, and now wanted to tackle the combination of state and failure
14:49:43 vilya joins (~vilya@user/vilya)
14:50:10 <ski> i'm assuming you're asking why the `a' in `State s a', and not just `s' ?
14:50:16 <bwe> correct
14:50:23 <ski> it's a good question
14:50:53 aljazmc joins (~aljazmc@user/aljazmc)
14:51:00 bwe *sighs*
14:51:26 × danse-nr3 quits (~danse@151.57.219.68) (Ping timeout: 256 seconds)
14:51:28 <bwe> it's because of using Monad Transformers?
14:51:33 <ski> no
14:51:39 <ski> it's simpler than that
14:51:45 zero listens
14:51:47 <ski> okay, so are you familiar with binary trees ?
14:52:22 <ski> could you e.g. define a data type of binary trees, with elements in the internal nodes, but not in the leaves ?
14:52:43 × m1dnight quits (~christoph@78-22-4-67.access.telenet.be) (Ping timeout: 264 seconds)
14:52:50 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
14:53:01 <ski> (monad transformers is a bit more advanced that what i think you need to be worrying about tackling here)
14:53:01 <bwe> you mentioned it'd be simpler?
14:53:20 <ski> yea, the issue is about the state monad (and monads in general)
14:53:50 <ski> i have an example in mind, pertaining to binary trees, that might help you see the point better
14:53:57 <ski> if you're willing to try it ?
14:54:00 zero ... https://yewtu.be/watch?v=WYysg5Nf7AU
14:54:23 <bwe> ski: binary tree: each node at max two children, that's what I've got
14:54:41 m1dnight joins (~christoph@78-22-4-67.access.telenet.be)
14:54:47 mechap joins (~mechap@user/mechap)
14:55:17 akegalj joins (~akegalj@141-136-147-15.dsl.iskon.hr)
14:55:21 <ski> (i mean .. i *could* just try to write a succinct answer for why the `a' .. but i'm not sure how helpful that would be, how easy it would be to understand. i'm thinking it would be more useful to gain some understanding, through an example. but if you really wish, i could try to give a short explanation)
14:55:52 <bwe> ski: either a node has children (1 or 2) or it carries a value, correct?
14:56:12 <ski> well, the `1' case is unnecessary. you could just have one of the two children be the empty tree
14:57:02 <zero> could we make a parallel with IO to show how parameterizing 'a' is useful?
14:57:08 <ski> so, an internal node always carries a value, and has two child trees. a tree can also be a leaf which in this case carries no value (so is an empty tree)
14:57:51 <ski> zero : i'm not sure at all to which extent bwe understands (even at a very basic practical level "how to use" to do simple I/O) `IO'
14:58:15 <zero> ski: ah ok. i just got here. shutting up now and listening as i'm interested in your example
15:01:04 <bwe> data Node a = Node (Node a) (Node a) | Leaf a -- something like this?
15:01:05 <bwe> zero: Let me watch that later. thanks for sharing it with me.
15:01:05 × dminuoso quits (~dminuoso@user/dminuoso) (Quit: ZNC 1.8.2 - https://znc.in)
15:01:05 × TMA quits (tma@twin.jikos.cz) (Ping timeout: 245 seconds)
15:01:06 <ski> (btw, i said "with elements in the internal nodes", so no elements at the leaves)
15:01:45 TMA joins (tma@twin.jikos.cz)
15:01:57 dminuoso joins (~dminuoso@user/dminuoso)
15:02:01 × dontdieych_ quits (~alarm@132.226.169.184) (Ping timeout: 245 seconds)
15:02:01 <bwe> ski: data Tree a = Node (Tree a) (Tree a) | Leaf
15:02:17 <ski> you'd need to put the `a' in the other alternative, in that case
15:02:47 <ski> well, i guess it works either way, not too much of a difference. do put the elements either in the binary node case (internal nodes), or in the nullary node case (leaves)
15:02:55 <ski> (whichever you prefer)
15:03:15 dontdieych_ joins (~alarm@132.226.169.184)
15:04:09 <ski> (if one's doing binary search trees, one do want the elements in the internal nodes. but we don't really need that here, it's just the shape of tree i first had in mind. but it doesn't matter for my example, really)
15:05:04 <bwe> ski: pls write what you specifically mean with internal nodes
15:05:09 × qqq quits (~qqq@92.43.167.61) (Remote host closed the connection)
15:05:33 <ski> oh, your `Node' alternative above is the "internal node" case (because that's the case that has child trees)
15:05:46 <ski> so, i'm suggesting either
15:06:02 <ski> data Tree a = Leaf a | Node (Tree a) (Tree a)
15:06:06 <bwe> ski: I've removed the a from the Leaf, therefore the Leaf is no more carrying a value
15:06:09 <ski> as you initially gave above
15:06:11 <ski> or else
15:06:20 <ski> data Tree a = Leaf | Node a (Tree a) (Tree a)
15:06:52 <bwe> oh, that Node is also carrying a value! not only its children!
15:06:54 <bwe> got that
15:06:56 <bwe> check
15:06:57 <ski> (but `data Tree a = Node (Tree a) (Tree a) | Leaf' is no good, since now there's no `a' elements at all in the tree)
15:07:06 <bwe> true
15:07:13 <ski> ok
15:07:13 <bwe> now it's obvious
15:07:44 <ski> so, now the task is : write a function that labels each element in the tree with an integer, counting from `0' upwards
15:07:58 × pretty_dumm_guy quits (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) (Quit: WeeChat 3.5)
15:08:07 <ski> iow, replace the `i'th element `x' with `(i,x)'
15:09:01 <bwe> so I need some state that is propagated and incremented each time we access some Tree a element
15:09:19 <bwe> Counter -> Tree -> (Counter, Tree)
15:09:23 <bwe> something like that
15:09:41 <ski> so `Node 2 (Node 3 Leaf Leaf) (Node 5 (Node 7 Leaf Leaf) Leaf)' should get turned into `Node (0,2) (Node (1,3) Leaf Leaf) (Node (2,5) (Node (3,7) Leaf Leaf) Leaf)'
15:09:44 pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655)
15:09:58 <ski> yea, we can take `Counter' to be `Integer' or `Int', for concreteness sake
15:10:18 <ski> (but you also need to provide the type parameter to `Tree' there)
15:10:50 <ski> the function shouldn't care about what the `x' elements in the tree are, so the input tree should have type `Tree a', so it works for any element type `a'
15:10:57 × aljazmc quits (~aljazmc@user/aljazmc) (Quit: Leaving)
15:11:24 aljazmc joins (~aljazmc@user/aljazmc)
15:11:33 <bwe> we don't do anything on a Leaf, right?
15:11:37 <ski> "so I need some state that is propagated and incremented each time we access some Tree a element" -- exactly. and i'd say it's good to solve this, both directly, and solve it using `State', to compare and contrast
15:11:54 <ski> right, no elements in a leaf, so nothing to update there
15:14:04 sabino joins (~sabino@user/sabino)
15:14:14 × haskellbridge quits (~haskellbr@069-135-003-034.biz.spectrum.com) (Remote host closed the connection)
15:14:57 <bwe> enumerateTree n (Node a b c) = (_, Node (n+1) b c)
15:15:09 <ski> (i guess i'd typically go for the naming `data Tree a = Leaf a | Branch (Tree a) (Tree a)' for the elements-at-leaves case, and `data Tree a = Empty | Node a (Tree a) (Tree a)' (or `Nil' or `Tip' instead of `Empty') for the internal-elements case .. but that doesn't really matter. you're fine as you are)
15:15:17 [_] joins (~itchyjunk@user/itchyjunk/x-7353470)
15:15:20 × [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Read error: Connection reset by peer)
15:15:32 <ski> bwe : yea, you need some recursion going there, somehow
15:15:56 zero thinks haskell has the most elegant code for tree traversals
15:16:07 <ski> for a `Node x l r', you need to traverse the two subtrees `l' and `r', labelling their elements (and getting back the updated counter)
15:16:38 <bwe> ski:
15:16:50 danse-nr3 joins (~danse@151.57.219.68)
15:16:50 <bwe> ski: so I do the children first?
15:17:44 haskellbridge joins (~haskellbr@069-135-003-034.biz.spectrum.com)
15:17:44 ChanServ sets mode +v haskellbridge
15:18:20 <sshine> zero, it's definitely easier to traverse trees when you're allowed to assume they exist indefinitely in memory. :-D
15:18:25 <ski> well, you need to pick some traversal order in which to visit the elements. for internal-element trees, the typical orderings would be preorder, inorder, and postorder (all three of those are depth-first). it'd also be possible to do breath-first ordering (walking through level after level), but that's more involved. i was thinking depth-first (which is what a simple recursion will give you)
15:18:49 <ski> and since we have `Node x l r', why not label first `x', then elements in `l', then elements in `r' ? (that'd be preorder)
15:19:05 <sshine> zero, (a comment about how ADTs in Rust are pretty great except when you want to pattern match across Box<T>s.)
15:19:17 <ski> (inorder would be : first `l', then `x', then `r'. postorder is : first `l', then `r', and finally `x')
15:20:16 <ski> .. it doesn't really matter which alternative you pick, as long as you realize there's a choice, and you know which alternative you're picking (and that you're sticking consistently to it, of course)
15:20:36 × lhpitn quits (~tn@mail.lebenshilfe-pi.de) (Ping timeout: 268 seconds)
15:21:27 Simikando joins (~Simikando@adsl-dyn216.91-127-84.t-com.sk)
15:22:06 <ski> (the example input->output i gave above was preorder too, btw)
15:24:20 absence joins (torgeihe@hildring.pvv.ntnu.no)
15:25:56 <bwe> ski: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L49-L55 -- promising: it compiles (for the Tree part)
15:26:13 <bwe> ski: I need a break. are you here around in 2 hrs?
15:28:08 <ski> bwe : yea, that looks about right
15:28:16 <ski> you're doing postorder, not preorder. but that's fine
15:28:30 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
15:28:49 <ski> (so you'll not get the exact same result as i suggested in my example input->output mapping)
15:28:50 <zero> sshine: i'm talking about this kind of poetry: https://paste.jrvieira.com/1700062115929
15:28:57 <ski> bwe : and yes
15:29:01 <absence> If I want to have multiple threads send messages to a queue, and have a pool of workers process those messages, is there a library I can use to set that up? I can implement it myself with TBQueue from stm or something, but a battle tested library would be nice. Just not sure what this concept is called, so I'm not sure what to search for.
15:29:25 <bwe> ski: great. thank you until here. I'll ping you then, ok?
15:30:16 <ski> (oh, you're also using preincrement, rather than postincrement. so if `n' is `0' initially, you'll still start labelling at `1'. that's not a problem, as long as you're aware that that's what you're doing
15:30:18 ystael joins (~ystael@user/ystael)
15:30:21 <ski> )
15:30:21 <ski> sure
15:31:11 × Simikando quits (~Simikando@adsl-dyn216.91-127-84.t-com.sk) (Ping timeout: 245 seconds)
15:32:40 <ski> zero : good old difference lists / list accumulator :)
15:33:14 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Ping timeout: 268 seconds)
15:33:33 × alp_ quits (~alp@2001:861:5e02:eff0:e086:39d1:f48d:94d6) (Ping timeout: 268 seconds)
15:34:20 <zero> ski: i have this snippet in a collection of 'beautiful code' snippets i keep :)
15:34:46 <ski> (:
15:35:32 × benjaminedwardwe quits (~benjamine@ool-45707daf.dyn.optonline.net) (Ping timeout: 250 seconds)
15:40:56 × vpan quits (~vpan@mail.elitnet.lt) (Quit: Leaving.)
15:40:56 <zero> heres another one in haskell: https://paste.jrvieira.com/1700062849674
15:43:10 <cstml> bwe: IdentityT does nothing. That's basically the point - it's a transformer that simply wraps a monad. All you can do with it is wrap/unwrap it.
15:44:06 <cstml> It wraps a Monad, just like Identity wraps a Type.
15:46:54 × bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "")
15:46:55 <cstml> StateT wraps a Monad and adds the methods of the State Monad to it. Then to unwrap out of it, you need to provide it with the initial state, etc.
15:47:27 zero ... https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-Tuple.html
15:47:50 gm joins (~gm@cpe-46-164-2-67.dynamic.amis.net)
15:55:49 <EvanR> IdentityT is the monad transformer which yields a monad with nothing different
15:58:52 <cstml> the only thing that is different is that in order to work with the transformed/wrapped monad is that you now have to `lift` to it.
15:59:24 <EvanR> which is the case for any MonadTrans
15:59:59 <EvanR> we usually think of monad transformers as "adding abilities". Can they remove abilities?
16:01:04 <EvanR> or is that impossible due to parametricity
16:02:49 × absence quits (torgeihe@hildring.pvv.ntnu.no) (Quit: leaving)
16:03:43 absence joins (torgeihe@hildring.pvv.ntnu.no)
16:04:25 <ski> zero : second doesn't include empty subset ?
16:05:25 <ski> .. is there a point to suggesting `IdentityT' above, rather than `Identity' ?
16:05:33 <c_wraith> EvanR: well, if they implement lift lawfully, they can't remove abilities.
16:05:33 <ncf> newtype VoidT m a = VoidT -- is this a lawful transformer?
16:06:25 <geekosaur> (what's its `lift`?)
16:06:30 <EvanR> what is return?
16:06:41 <ncf> everything is the unique function to the unit type
16:06:44 <ski> const VoidT
16:07:37 <EvanR> alright then
16:07:43 <c_wraith> Hmm. I suppose the MonadTrans laws don't forbid the empty transformer
16:07:56 Simikando joins (~Simikando@adsl-dyn216.91-127-84.t-com.sk)
16:08:15 × euleritian quits (~euleritia@x52717980.dyn.telefonica.de) (Read error: Connection reset by peer)
16:08:32 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
16:09:56 idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c)
16:10:36 <cstml> bwe: check this example out. https://play.haskell.org/saved/dGZnby3d
16:11:59 <cstml> I'd hazard myself and say: it's as simple as that ^. But yeah, hope it gets the intuition across.
16:15:24 <EvanR> also data VoidT m a -- no constructors --
16:17:08 <ski> well, `return's not total
16:18:38 gm_ joins (~gm@cpe-46-164-2-67.dynamic.amis.net)
16:18:54 <EvanR> ah, the total subset of haskell xD
16:20:09 × gm quits (~gm@cpe-46-164-2-67.dynamic.amis.net) (Read error: Connection reset by peer)
16:20:09 gm_ is now known as gm
16:20:11 × lortabac quits (~lorenzo@2a01:e0a:541:b8f0:93f2:661e:d61:f6f4) (Quit: WeeChat 3.5)
16:20:59 notzmv joins (~zmv@user/notzmv)
16:22:00 <monochrom> You can always try ProxyT instead. Almost as good. :)
16:23:31 <monochrom> Informtation theoretically, empty information does not mean empty set, instead singleton set.
16:24:25 mvk joins (~mvk@2607:fea8:5c9a:a600::900d)
16:24:33 × mvk quits (~mvk@2607:fea8:5c9a:a600::900d) (Client Quit)
16:25:28 <ski> > logBase 2 0
16:25:29 <lambdabot> -Infinity
16:26:19 <ncf> trick i got from conor: Const 0 is a functor but not an applicative, Const 2 is an applicative but not a monad, Const 1 is a monad
16:26:53 <monochrom> That is beautiful. :)
16:30:50 Square joins (~Square@user/square)
16:32:55 × gm quits (~gm@cpe-46-164-2-67.dynamic.amis.net) (Quit: gm)
16:33:11 gm joins (~gm@cpe-46-164-2-67.dynamic.amis.net)
16:33:26 × Square2 quits (~Square4@user/square) (Ping timeout: 256 seconds)
16:33:27 Inst parts (~Inst@120.244.192.250) (Leaving)
16:33:55 waleee joins (~waleee@h-176-10-144-38.NA.cust.bahnhof.se)
16:36:32 × lisbeths quits (uid135845@id-135845.lymington.irccloud.com) (Quit: Connection closed for inactivity)
16:40:36 <EvanR> and Const 3?
16:40:51 tzh joins (~tzh@c-71-193-181-0.hsd1.or.comcast.net)
16:42:16 <ncf> Const n with n ≥ 2 is an applicative but not a monad
16:42:55 × machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 268 seconds)
16:43:17 <EvanR> uniquely?
16:43:22 <dolio> No.
16:43:51 <ncf> applicatives correspond to monoid structures on Fin n
16:44:12 × Simikando quits (~Simikando@adsl-dyn216.91-127-84.t-com.sk) (Ping timeout: 256 seconds)
16:44:19 tango88 joins (~tango88@45.129.56.151)
16:50:17 Simikando joins (~Simikando@adsl-dyn216.91-127-84.t-com.sk)
16:52:18 × gm quits (~gm@cpe-46-164-2-67.dynamic.amis.net) (Quit: gm)
16:52:48 × Pozyomka quits (~pyon@user/pyon) (Server closed connection)
16:53:07 Pozyomka joins (~pyon@user/pyon)
16:54:00 ChaiTRex joins (~ChaiTRex@user/chaitrex)
16:54:59 × johnw quits (~johnw@69.62.242.138) (Quit: ZNC - http://znc.in)
16:57:37 econo_ joins (uid147250@id-147250.tinside.irccloud.com)
17:02:44 × ChaiTRex quits (~ChaiTRex@user/chaitrex) (Quit: ChaiTRex)
17:04:51 alp_ joins (~alp@2001:861:5e02:eff0:2593:ef1a:f448:eef7)
17:08:29 × rosco quits (~rosco@175.136.157.149) (Quit: Lost terminal)
17:10:54 <danse-nr3> someone mentioned "chordify" in haskell cafe', but i did not find any haskell project with that name. Is that a company running haskell?
17:16:03 <danse-nr3> i think it's fair to add a link ... https://mail.haskell.org/pipermail/haskell-cafe/2023-November/136443.html
17:17:27 × Simikando quits (~Simikando@adsl-dyn216.91-127-84.t-com.sk) (Ping timeout: 268 seconds)
17:19:19 × waleee quits (~waleee@h-176-10-144-38.NA.cust.bahnhof.se) (Quit: WeeChat 4.1.0)
17:22:17 thegman joins (~thegman@072-239-207-086.res.spectrum.com)
17:22:41 <EvanR> choridy - instance chords for any song
17:22:49 <EvanR> man
17:22:52 <EvanR> chordify
17:23:13 <danse-nr3> oh nice, i will took that up. Thanks!
17:25:39 <danse-nr3> huh ... this one chordify.net ?
17:26:29 × VioletJewel quits (~violet@user/violetjewel) (Server closed connection)
17:26:42 × euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Ping timeout: 246 seconds)
17:26:43 VioletJewel joins (violet@user/violetjewel)
17:27:35 euleritian joins (~euleritia@x52717980.dyn.telefonica.de)
17:30:18 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
17:31:21 × ph88 quits (~ph88@2a02:8109:9e26:c800::302a) (Quit: Leaving)
17:32:35 Simikando joins (~Simikando@adsl-dyn216.91-127-84.t-com.sk)
17:34:40 × danse-nr3 quits (~danse@151.57.219.68) (Read error: Connection reset by peer)
17:35:32 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Remote host closed the connection)
17:35:35 danse-nr3 joins (~danse@151.43.130.136)
17:35:46 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
17:40:28 ec_ is now known as ec
17:41:16 <EvanR> danse-nr3, looks like they use haskell somehow https://www.reddit.com/r/haskell/comments/q6q4zr/job_haskell_developer_chordify/
17:42:53 <danse-nr3> oh i see, there is also github.com/chordify. Thanks
17:45:23 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
17:50:30 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 256 seconds)
17:51:02 × chele quits (~chele@user/chele) (Remote host closed the connection)
17:51:41 × terrorjack quits (~terrorjac@2a01:4f8:c17:87f8::) (Quit: The Lounge - https://thelounge.chat)
17:54:33 terrorjack joins (~terrorjac@2a01:4f8:c17:87f8::)
17:59:03 ChaiTRex joins (~ChaiTRex@user/chaitrex)
18:00:08 × alp_ quits (~alp@2001:861:5e02:eff0:2593:ef1a:f448:eef7) (Ping timeout: 256 seconds)
18:01:31 telser joins (~quassel@user/telser)
18:02:47 johnw joins (~johnw@69.62.242.138)
18:05:32 × euleritian quits (~euleritia@x52717980.dyn.telefonica.de) (Read error: Connection reset by peer)
18:05:51 euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de)
18:12:06 <bwe> ski: ping
18:12:44 <ski> syn
18:13:33 <bwe> ski: latest version is https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4 -- I've incorporated your comments
18:14:28 derpyxdhs joins (~Thunderbi@user/derpyxdhs)
18:14:48 <bwe> ski: where were we? why were we building the Tree example? it was about propagating the State through the function, as input through to output
18:14:59 <bwe> nice example that Tree, btw
18:15:30 <bwe> cstml: I've seen your piece and will consult it later, as of now thanks.
18:16:16 <tango88> hi. i was wondering if `data A = A!Int` is valid grammatically and if so, why doesn't GHC accept it?
18:17:00 <cstml> bwe: no worries - hope "you get it".
18:17:14 <ski> bwe : oh, you've actually introduced a bug now, as compared to the last version of `enumerateTree'
18:17:37 <bwe> ski: I should have sticked with the good-enough version :)
18:17:45 <bwe> cstml: thanks for your faith!
18:18:02 <ski> tango88 : works here
18:18:18 <ski> bwe : can you identify the bug ?
18:18:44 <ski> @let data A = A!Int
18:18:46 <lambdabot> Defined.
18:18:56 <ski> > case A undefined of A _ -> ()
18:18:59 <lambdabot> *Exception: Prelude.undefined
18:19:15 <cstml> bwe: keep at it - it's really not as hard as it might seem. I have faith.
18:22:58 <ski> (bwe : i could give hints, if you want any. but perhaps you'd first like to try and see if you can identify a problem, and then perhaps what is causing it)
18:23:19 <bwe> ski: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L58
18:23:55 <bwe> if I label sth. with an incremented number, the state should incorporate that - which it didn't
18:24:14 <ski> yep, right. you weren't incrementing the counter at all
18:24:22 × derpyxdhs quits (~Thunderbi@user/derpyxdhs) (Quit: derpyxdhs)
18:24:47 <ski> so you were passing the same counter number through all the computation, labelling every element with the same number (one more than the counter)
18:25:30 <ski> ok, good, now you're back to preincrement (so if you start at zero, first element will be labelled with one)
18:26:03 <ski> my `Branch 2 (Branch 3 Leaf Leaf) (Branch 5 (Branch 7 Leaf Leaf) Leaf)' example was formulated in terms of labelling first element at zero, not one
18:27:02 <ski> if you want to, you could figure out what makes your code preincrement and not postincrement. (it could be nice to understand.) but if you'd rather move on, that's also fine. it's not too important for the main lesson
18:27:09 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Remote host closed the connection)
18:27:20 <bwe> in (n2+1, Branch (n2, x) l' r')
18:27:30 <ski> that would postincrement, yep
18:28:05 <ski> `n2' is the current counter, after labelling `l' and `r'. so you're labelling the element with the current counter, and *then* incrementing the counter on the way out
18:28:41 <ski> (this last version line above is doing that i mean)
18:28:58 <bwe> so we are on line with your example output
18:28:58 <ski> okay
18:29:02 <ski> yep
18:29:19 caryhartline joins (~caryhartl@168.182.58.169)
18:29:27 waleee joins (~waleee@h-176-10-144-38.NA.cust.bahnhof.se)
18:29:41 <tango88> ski: it seems that this stopped working with GHC 9
18:29:41 <tango88> https://play.haskell.org/saved/HnpUO4at
18:29:42 <tango88> this works on GHC 8.10.7, but it doesn't on GHC 9.0.2
18:30:13 × Simikando quits (~Simikando@adsl-dyn216.91-127-84.t-com.sk) (Ping timeout: 268 seconds)
18:30:26 <ski> so, what you've done now, is to manually "thread" the state (the counter) through your computation. into each recursive call, and also out of it, and then into the next recursive call. and incrementing it, while passing through each element that you encounter, and at the end of a node give back the current counter, so far, as part of output
18:30:38 <ski> curious, tango88
18:30:44 <ski> tango88 : what if you add a space before `!' ?
18:31:15 <ski> bwe : would you like to see how to do preorder and inorder, too ? or should we move on ?
18:31:35 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
18:31:55 <ski> (breath-first is more involved, requires changing the code more seriously)
18:32:25 <bwe> let's do preorder and inorder :)
18:33:02 <geekosaur> % data A = A!Int
18:33:02 <yahb2> <interactive>:15:11: error: Not a data constructor: ‘!’
18:33:15 <ski> (oh, and if it isn't clear, "inorder" is named so, because the element in a node is encountered inbetween traversing the two child subtrees. while for "preorder", the element is before them, and for "postorder", the element is after them)
18:33:37 <ski> % data A = A !Int
18:33:38 <yahb2> <no output>
18:33:49 <geekosaur> I *think* this was part of rationalizing the way prefixes are parsed
18:33:53 <ski> bwe : any hunch of how to adapt the code ?
18:34:51 <ski> bwe : btw, explicitly naming `n2+1' as (say) `n3' in the postorder case could be a preliminary step
18:35:33 <tango88> is the `data A = A!Int` grammar itself valid according to the report?
18:36:05 <geekosaur> yes. but ghc has a lot of extensions including to where ! is valid (BangPatterns)
18:36:22 <tango88> i see, thanks
18:36:23 <bwe> ski: I "just" need to swap the numbers for x and l
18:37:01 <geekosaur> and each extension had its own parsing rules. in 9.x those rules were rationalized, with the result that prior spaces or other non-expression syntax is required for prefixes like ! and ~ (and unary -)
18:37:29 <ski> % data A = (A)!Int
18:37:30 <yahb2> <interactive>:19:13: error: Not a data constructor: ‘!’
18:38:01 <probie> Is it valid according to the report? `data A = A:!Int` is, but `!` isn't a valid constructor
18:38:17 ski sometimes wishes to be able to say `(x +*+ y) = ..x..y..'
18:38:51 <geekosaur> I was under the impression it would parse with A as the constructor since ! couldn't be, then ! would be recognized as a strictness indicator
18:39:13 <geekosaur> conceivably this is a bug in ghc9.x as a result
18:39:42 <dolio> :! is a valid constructor name.
18:39:48 <geekosaur> but ! is not
18:40:05 <geekosaur> the question being why `data A = A!Int` is trying to parse it as one
18:40:20 <geekosaur> instead of as `A !Int`
18:40:40 <probie> Don't mind me, for some reason I thought that strictness annotations were a GHC thing, but the report says I'm silly
18:41:02 <dolio> Yeah, I'm not sure why that'd parse any different.
18:41:03 <geekosaur> strictness annotations in `data` are standard. strictness annotations in patterns are an extension
18:42:01 × caryhartline quits (~caryhartl@168.182.58.169) (Quit: caryhartline)
18:43:19 <probie> and they've been there since at least Haskell 1.4
18:44:01 <dolio> You can't write `A ! Int`, either, even though I think the report says that's fine.
18:44:02 ski still doesn't really like `@' syntax for type applications
18:44:46 × jinsun quits (~jinsun@user/jinsun) (Read error: Connection reset by peer)
18:45:51 <ski> (occasionally i'd like to be able to say stuff like `foo_f@(foo f) x = ..foo..f..foo_f..x..')
18:49:23 <bwe> ski: here we go: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L58-L86
18:51:15 <ski> great :)
18:51:30 × td_ quits (~td@i53870918.versanet.de) (Ping timeout: 268 seconds)
18:51:34 <ski> (except i'd replace `n2+1' with `n3' in the postorder, so that it's not a dead binding)
18:51:44 <bwe> ski: I'd ping you another time on that breath-first ordering
18:51:47 ft joins (~ft@p508db3bc.dip0.t-ipconnect.de)
18:51:57 <ski> you're welcome, if i'm around
18:52:10 <bwe> cool. Yep, replaced that.
18:52:21 <ski> ok
18:52:28 <ski> so, onto `State', then ?
18:52:34 <bwe> Now, I am excited about that, yup.
18:52:53 td_ joins (~td@i53870930.versanet.de)
18:53:11 <ski> any idea where to start, with that ?
18:54:45 <bwe> ski: we are using that counter everywhere, that's our context. so if we could just track that in the background every time we increment or get the current state...
18:55:06 <ski> oh, it might also be reasonable (depending on what you're aiming for) to do a wrapper function which initializes the counter at zero (and perhaps not making the version that takes the counter as an input public, possibly defining it (as a "worker") inside a `where' of the "wrapper")
18:56:05 × tango88 quits (~tango88@45.129.56.151) (Quit: Client closed)
18:56:06 <ski> one could e.g. call the previous version `enumerateTreeFrom', and the one that starts at zero, `enumerateTree'
18:56:34 <bwe> any idea how I could integrate all three variants into one?
18:56:40 <ski> (you could also add `inorder',`preorder',`postorder', or perhaps just `in',`pre',`post' for short, to those names, to differentiate between the different traversal orders)
18:56:55 <ski> well ..
18:57:24 <ski> you could, but i'm not sure how helpful it would be here (you'd still have at least some amount of code duplication, i think)
18:57:47 <bwe> let's do some case here
18:58:04 <ski> (one approach would be to make `data TraversalOrder = Preorder | Inorder | Postorder', and pass an extra input of type `TraversalOrder')
18:58:18 <bwe> :) I was just about doing that
18:58:37 <ski> (but doing worker-wrapper would also be beneficial, in that case)
18:59:40 <ski> (are you familiar with what i mean by "worker-wrapper" ?)
19:00:32 <bwe> let me do it and we'll see, ok?
19:01:01 <ski> sure
19:03:58 Simikando joins (~Simikando@adsl-dyn216.91-127-84.t-com.sk)
19:07:27 <bwe> the worker-wrapper would then return only the tree or the state also?
19:09:38 k` joins (~user@152.7.255.206)
19:10:08 × sord937 quits (~sord937@gateway/tor-sasl/sord937) (Quit: sord937)
19:10:43 <ski> well, i guess it's up to your judegment, really
19:10:55 <ski> perhaps one'd also like to get a count of the number of elements ?
19:11:03 <ski> or perhaps just labelling is the main focus ?
19:11:18 <ski> the latter option seems the simpler interface, anyway
19:11:19 <bwe> updated: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4 -- and proud of the evolved solution!
19:13:26 <bwe> fast-forward to state: if we had the counter implicitly as the context we work in, we'd just need a get and inc function; then we'd basically factored out the management of the counter (that's what we do with the n1, n2+1 etc).
19:13:47 <bwe> just an intuition here, might be prematurely, though
19:14:58 <ski> bwe : right. (btw, it would be possible to factor out the common `Branch' part (after the `in's) from the `case' .. although it's not entirely clear whether it would be worth it). now notice that `order' is passed on recursively into `enumerateTreeFrom', but is never changed
19:16:19 <ski> "we'd just need a get and inc function; then we'd basically factored out the management of the counter (that's what we do with the n1, n2+1 etc)." -- yes (although it's not uncommon to merge those into a single operation, perhaps called `tick', which both increments and gets the current counter state)
19:18:03 <bwe> let's wrap Tree a with a State then?
19:18:26 <ski> sure
19:18:50 <bwe> Int (Tree a) -> Int (Tree (Int, a)) -- I've dropped the TraversalOrder here
19:19:08 <bwe> (and yeah, that's not the way we'll do it, sure)
19:19:12 × thegeekinside quits (~thegeekin@189.141.80.123) (Remote host closed the connection)
19:19:18 <bwe> but that's the idea for me
19:19:38 <ski> did you mean to type `State' somewhere in there ?
19:20:25 ski would also like to see `order' not passed around as an argument to (the locally defined) `enumerateTreeFrom'
19:20:27 <bwe> Eventually but it clicked here for me: Tree a happens within a context of that counter that is Int.
19:20:45 <ski> you could say as much
19:21:01 <ski> well .. at least something like that
19:21:03 <bwe> that State term confuses me still -- keep it away from me!
19:21:11 <ski> hehe :)
19:21:40 Inst joins (~Inst@120.244.192.250)
19:21:44 <bwe> so, let's factor out Int and TraversalOrder into State
19:21:50 <ski> @kind Int (Tree String)
19:21:51 <lambdabot> error:
19:21:51 <lambdabot> • Expected kind ‘* -> k0’, but ‘Int’ has kind ‘*’
19:21:51 <lambdabot> • In the type ‘Int (Tree String)’
19:21:57 <bwe> (Int, Traversalorder)
19:22:07 <ski> why `Traversalorder' ?
19:22:44 <bwe> wait
19:22:49 <ski> (i've been trying to get at this with my comments about worker-wrapper, and the `order' parameter)
19:22:58 <bwe> I'll put it into the worker-wrapper that is all
19:24:44 <bwe> ski: that's the way to do it: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L55
19:25:07 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Remote host closed the connection)
19:25:12 <bwe> so, let's put only the counter into the State, because that changes, order doesn't - as you mentioned earlier
19:25:43 × danse-nr3 quits (~danse@151.43.130.136) (Ping timeout: 268 seconds)
19:25:53 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Remote host closed the connection)
19:26:15 dcoutts joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
19:26:31 <ski> bwe : exactly, you don't need to pass around an unchanging parameter in a locally defined worker, you can just "grab it frmo the air" out of the wrapper
19:27:08 <mauke> how closury
19:27:46 <bwe> ski: so, how do I define the tick?
19:28:06 <ski> (or, even if you'd pass it on as a parameter, note that `order' is only passed "downwards" into recursive calls. it's not returned from them. it's not "threaded" from one call to the next (like the counter is). so `order' is *not* a piece of state. we say it's an "environment" (compare with environment variables in OS processes, which are inherited "downwards" to children processes))
19:28:15 danse-nr3 joins (~danse@151.43.130.136)
19:28:54 ski coclosures mauke
19:29:13 <bwe> ski: before I'd prefer to return only the Tree without the counter
19:29:15 <ski> bwe : well, what could be a reasonable type signature for `tick', to begin with ?
19:29:57 <ski> bwe : you can do that, by adapting the initial call to the worker, in the wrapper, adding some postprocessing (and not just the preprocessing of initializing the counter)
19:30:24 <ski> (my last two comments were unrelated to each other)
19:31:39 <bwe> tick :: State Int -> (Int, State Int) -- it needs access to some state and returns a new number including a new state
19:31:39 × dcoutts quits (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net) (Ping timeout: 246 seconds)
19:32:08 Tuplanolla joins (~Tuplanoll@91-159-68-236.elisa-laajakaista.fi)
19:32:20 <mauke> ah
19:32:39 <mauke> that's insufficiently magical :-)
19:33:04 <mauke> it's also a kind error
19:33:08 <bwe> but I am not sure whether we actually return the new state, since we want to factor it out, so why return it?
19:33:09 <mauke> State takes two type parameters
19:33:52 <mauke> a value of type 'State s a' is a computation that can return a result of type 'a' while making use of state of type 's'
19:33:57 <bwe> mauke: I am currently in the process of learning State, so please don't assume that I know that it's taking something in :).
19:34:00 × dexter2 quits (dexter@2a01:7e00::f03c:91ff:fe86:59ec) (Server closed connection)
19:34:28 dexter2 joins (dexter@2a01:7e00::f03c:91ff:fe86:59ec)
19:34:38 × Simikando quits (~Simikando@adsl-dyn216.91-127-84.t-com.sk) (Remote host closed the connection)
19:34:40 <ski> bwe : it may help to realize that `State s a' does not encapsulate a state (version). it represents a state *transformer*, that given a previous state computes a next state (and also a separate "result")
19:34:53 <mauke> since tick wants to return a result of type Int while making use of some implicit state (also of type Int), it would be tick :: State Int Int
19:34:56 <ski> er, state *transformation*, i meant to say
19:35:10 <mauke> or was that a spoiler?
19:35:29 <monochrom> You should start with the idea of state transition functions, Int -> Int. Then you say you also want an output. That becomes Int -> (a, Int).
19:35:39 <bwe> ski: so the term State is completely misleading
19:35:41 <ski> "I am not sure whether we actually return the new state, since we want to factor it out, so why return it" -- we want to abstract it out of sight .. not quite the same as factor it out
19:36:03 <bwe> ski: abstract it out of sight
19:36:05 <monochrom> Oh haven't you heard: All meaningful names are misleading. >:)
19:36:23 <monochrom> Just look at our "data", "type", and "newtype".
19:36:40 <ski> mauke : yeap :p
19:36:53 <monochrom> And outside, "RAII", "bus factor", and "test pollution" aren't that great either.
19:37:30 <monochrom> The first time I heard "bus factor" I thought it was referring to hardware and for example PCI 5 has a higher bus factor than PCI 4.
19:37:40 <ski> bwe : it's an abbreviation (`State'). yes, without the proper background understanding, i understand how it could easily be taken in the wrong way
19:38:00 <mauke> .oO( Statefully? )
19:38:04 <bwe> ski: who can I blame of naming it so?
19:38:11 <ski> Wadler, maybe ?
19:38:19 <ski> (or perhaps Moggi ?)
19:38:20 <monochrom> Human nature.
19:38:35 <monochrom> Every human thinks the name they coin makes total sense to everyone else.
19:38:51 <ski> bwe : btw, you definitely should read Philip Wadlers papers introducing monads as a programming technique
19:39:14 <ski> (they're quite readable, i'd say)
19:39:26 <monochrom> The cold hard truth is that names are insider jokes.
19:40:05 <bwe> ski: so, what's the transition step between tick :: Int -> Int to the State version? I feel it could help if I see them side-by-side.
19:40:08 <k`> Yeah, adding `ful` to the end might have made it more clear.
19:40:39 <monochrom> But perhaps Stateful is better for the type class (MonadState). :)
19:40:44 <k`> Then you could uncreatively name your state dictionary "State"
19:41:00 <k`> monochrom: True.
19:41:32 <monochrom> Int->Int is isomorphic to Int->((),Int).
19:41:50 <monochrom> OK I said I hated the word "isomorphic". :)
19:41:54 <bwe> iow?
19:42:49 <monochrom> It is possible that the Wadler papers or lecture notes will help.
19:43:00 <k`> monochrom: \ x -> (error "Here is some information", x - 1)
19:43:07 <dolio> I don't think it's misleading.
19:43:29 <mauke> have we done @unmtl yet?
19:44:04 <ski> bwe : <https://homepages.inf.ed.ac.uk/wadler/topics/monads.html>. start from the oldest. iirc, "The essence of functional programming","Combining monads","Comprehending monads","Monads for functional programming","Imperative functional programming","How to declare an imperative" are the main important ones (and "Monads and composable continuations" is also quite interesting)
19:44:27 <monochrom> Actually https://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm is exactly about the state monad.
19:45:00 <ski> bwe : well, if we start with `tick :: Int -> Int', (focusing just on the state update, ignoring getting the current state), how would you define that ?
19:46:04 <ski> bwe : sorry, "iow" is short for "in other words"
19:46:09 <bwe> tick :: State Int => Int -- very cautious try and error
19:46:24 × astra quits (sid289983@id-289983.hampstead.irccloud.com) (Server closed connection)
19:46:33 <ski> (i didn't even realize i had used the abbreviation, had to go look for it)
19:46:33 <bwe> ski: I reasoned that after some time so recycled it by sending it to monochrom
19:46:45 astra joins (sid289983@id-289983.hampstead.irccloud.com)
19:47:05 <mauke> @unmtl State Int => Int
19:47:05 <lambdabot> State Int => Int
19:47:10 <mauke> heh
19:47:26 <ski> mauke : too early for 'unmtl'
19:47:42 <mauke> or too late, depending on your approach
19:47:46 <ski> could be
19:47:50 <mauke> but I just wanted to see what would happen
19:48:05 <mauke> didn't expect that :-)
19:48:19 <bwe> ski: the function just returns Int, the context is our State
19:48:40 <bwe> so from inside the function we access that State we abstracted away
19:49:00 <ski> bwe : anyway, `=>' suggests some use of type classes. we're not going to use any type class here (except eventually `Monad', and that won't show up in the type signature)
19:49:13 <ski> so, go back to `tick :: Int -> Int' ?
19:49:39 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
19:50:01 <ski> monochrom : when's that from ?
19:50:52 <ski> "so, what's the transition step between tick :: Int -> Int to the State version? I feel it could help if I see them side-by-side." -- yes, i was thinking the same
19:51:02 <ski> bwe ^
19:51:21 <k`> monochrom's hint was `Int -> ((), Int)`.
19:51:53 <ski> we'll get to it, sooner or later
19:52:24 <Inst> just curious, bwe, how much of haskell do you know so far, and where are you coming from?
19:53:42 <k`> @unmtl State i a
19:53:42 <lambdabot> i -> (a, i)
19:54:33 <bwe> Inst: I've written quite some; but avoided Monad transformers since. Quite recently I intuitively began using <- assignments in do notation to simplify flow of operations. for example a function that returns Maybe Int.
19:54:38 × Square quits (~Square@user/square) (Remote host closed the connection)
19:54:47 <k`> @type (,) ()
19:54:48 <lambdabot> b -> ((), b)
19:55:00 <bwe> Inst: What was your impression of my Haskell proficiency?
19:55:33 <Inst> i don't feel qualified to judge, but, first, state doesn't have to be implemented via monad transformers, although it usually is for convenience purposes
19:55:42 × kronicma1 quits (user24323@neotame.csclub.uwaterloo.ca) (Server closed connection)
19:56:00 kronicma1 joins (user39425@neotame.csclub.uwaterloo.ca)
19:56:03 <ski> yea, we're doing implementation of basic monads, to begin with. then combining multiple effects into the same monad is the plan
19:56:22 <Inst> second, i've been told that state is usually when you really "get' monads
19:56:45 <ski> (the goal at the moment is to really understand how `State' and its `Monad' instance works, including how to apply it for stateful problems)
19:56:52 <Inst> since a lot of people get trapped with the flawed "wrapper" intuition that unfortunately, Maybe and List get you into
19:57:20 <mauke> s -> ( , s) is a wrapper!
19:57:38 ski wraps up the picnic
19:58:03 feetwind joins (~mike@user/feetwind)
19:58:23 ski . o O ( `picnic :: Food -> (Satisfaction,Food)' )
19:59:07 <probie> `State Food Satisfaction` sounds like an instruction
19:59:20 <ski> you could state that
20:00:05 <bwe> ski: do you want to continue this now or prefer of doing it another time?
20:00:43 <k`> probie: I don't like what that implies about what's happening with the food. I prefer ReaderT for food.
20:01:25 <ski> it's fine atm, if you feel fresh and clear-headed enough to continue. but perhaps you may already have enough (picnic ?) food for thought to digest (what with the traversal orders, and what happened in `enumerateTree' so far), so to prefer continuing later ?
20:01:56 <Inst> don't worry, it was a huge pain in the ass for me as well
20:02:02 <ski> k` : there may be leftovers
20:02:25 <Inst> i'd rather start with data Proxy a = Proxy and why we say it's a monad :)
20:02:48 <ski> bwe : see reply above
20:03:26 <bwe> ski: can we continue a little more? I feel excited to grasp that StateFUL thing
20:03:38 <ski> sure
20:03:54 <k`> ski: To deal with leftovers you may need to stream the food.
20:04:25 ski . o O ( "Throw, throw -- throw your food, gently down the stream." )
20:04:40 <feetwind> i saw https://hackage.haskell.org/package/qualified-imports-plugin and was wondering, has anyone made a proposal to actually allow type names to act as qualified modules? so you could actually have `module Data.Text(type Text, module Text(unpack, pack, foldr, foldl, ...))`
20:05:00 <feetwind> then just have eg `import Data.Text; foo = Text.pack "asdf"`
20:05:23 <k`> Unfortunately I heard that conveyor belt sushi is going away.
20:05:45 <ski> bwe : so you desired to compare and contrast two versions of `tick' (and i agree), one "explicit" (like your `enumerateTreeFrom' so far's explicit), and one "implicit", using `State'
20:06:01 <bwe> right
20:06:14 <ski> so, should we try the first part ?
20:06:30 <ski> how to implement `tick :: Int -> Int' ?
20:06:32 <bwe> yes
20:07:11 <bwe> tick n = n+1
20:07:15 <ski> right
20:07:20 <bwe> or short tick = (+1)
20:07:25 <ski> now, that's only handling the update of the counter state
20:07:36 <bwe> ah1
20:07:37 <bwe> !
20:07:44 <ski> but, we'd also like to get a "reading" of the state, as a "separate result"
20:07:54 <feetwind> an OverloadedModules extension to do it would be nice and then i'd never have to write Text.Text or `import Data.Text (Text)` again :')
20:07:56 <ski> any idea how that could look like ?
20:08:06 <ski> (you need to change the type signature, too)
20:08:15 <bwe> (n, n+1) for example
20:08:23 <ski> yep
20:08:26 <ski> (signature being ?)
20:08:29 <feetwind> same vain, has anyone proposed import aliases a la rust/typescript, like import Data.Text.Lazy (Text as LazyText) ?
20:08:29 <bwe> tick :: Int -> (Int, Int)
20:08:32 ski nods
20:08:44 <ski> now, can you recall how `State' was defined ?
20:09:45 <ski> feetwind : there can be multiple data types declared in a module
20:10:01 <bwe> s -> (a, s)
20:10:23 <ski> yea, but what's the full `data' type declaration ?
20:10:47 × haritz quits (~hrtz@user/haritz) (Server closed connection)
20:11:04 haritz joins (~hrtz@2a02:8010:65b5:0:6009:6384:e3cb:2220)
20:11:38 <ski> (it may help to have some things in front of our eyes, in the discussion)
20:11:58 <bwe> newtype State s a = State (s -> (a, s))
20:12:01 <ski> right
20:12:08 <bwe> chaka
20:12:42 <ski> now, to more easily refer to the type, and to the data constructor, separately, i'll pretend that this actually was declared as
20:12:52 <ski> newtype State s a = MkState (s -> (a, s))
20:12:55 × haritz quits (~hrtz@2a02:8010:65b5:0:6009:6384:e3cb:2220) (Changing host)
20:12:55 haritz joins (~hrtz@user/haritz)
20:13:17 <ski> anyway, you're right that we should look at the `s -> (a,s)' part now
20:13:56 <bwe> Int -> (Int, Int) vs. s -> (a,s)
20:14:05 <ski> this is a function type, getting a state (version) as input, and computing back as result some value (of type `a'), together with a (presumably updated) state as output
20:14:09 <bwe> tick vs. MkState
20:14:38 <ski> (for hysterical raisins, the output state part is the latter part of the pair, and the result value is the former part)
20:14:50 <ski> now, please recall your current definition of `tick'
20:15:10 × akegalj quits (~akegalj@141-136-147-15.dsl.iskon.hr) (Quit: leaving)
20:15:17 <bwe> tick :: Int -> (Int, Int)
20:15:49 <ski> (and the defining equation ?)
20:16:03 <bwe> tick = (n, n+1)
20:16:07 <ski> thank you
20:16:46 <ski> now, perhaps i'm belaboring the point here .. but note that in `(n,n+1)', the `n' (former) part is thus the "result value", while the `n+1' (latter) part is the "updated/output state"
20:17:10 <ski> (it may not always be so clear, since both have the same type. so it's good to be explicit about what is what)
20:18:18 <ski> so, yea, we match the concrete type `Int -> (Int,Int)' (the type of `tick') with the type `s -> (a,s)' (which is the representation type of the data type `State s a', the type of what's "contained inside" that)
20:18:21 × incertia quits (~incertia@209.122.71.127) (Ping timeout: 260 seconds)
20:18:22 <bwe> the first is the getter, the second the setter?
20:18:41 <bwe> (while in the State it's flipped order)
20:18:44 <k`> @t get
20:18:44 <lambdabot> Maybe you meant: tell thank you thanks thesaurus thx tic-tac-toe ticker time todo todo-add todo-delete type v @ ? .
20:18:56 <k`> @type get
20:18:57 <lambdabot> MonadState s m => m s
20:18:58 <ski> .. not quite .. but something akin to that, i guess
20:19:17 <bwe> not setter, the state value
20:19:24 <ski> yes
20:19:50 incertia joins (~incertia@209.122.137.252)
20:19:54 <ski> anyway, matching the types, we see that `s' must be `Int', and `a' happens to be `Int', so `State s a' becomes `State Int Int'
20:20:28 <ski> so, if we're wrapping `tick' (a state *transformation* function) inside `MkState', we will get something of type `State Int Int'
20:20:33 <ski> that's clear ?
20:20:56 <bwe> tick'' :: _ -> State Int Int
20:21:01 <ski> ("while in the State it's flipped order" -- no. same order in `tick' above, as in `State')
20:21:07 <bwe> k
20:21:32 <ski> yea .. except there's now no (*visible* !) argument
20:21:38 <ski> so there's no `_ -> '
20:22:01 <feetwind> ski, sorry not really what i mean
20:22:14 <feetwind> i think the answers are basically, no :)
20:22:14 <k`> @type state
20:22:15 <lambdabot> MonadState s m => (s -> (a, s)) -> m a
20:22:17 <ski> (you could perhaps call the original version `tick', and the `State' version `tickS', to distinguish them from each other)
20:23:04 <bwe> ah, we abstracted away the "s ->" part into the StateFUL!
20:23:11 × tinwood quits (~tinwood@canonical/tinwood) (Server closed connection)
20:23:24 tinwood joins (~tinwood@general.default.akavanagh.uk0.bigv.io)
20:23:24 × tinwood quits (~tinwood@general.default.akavanagh.uk0.bigv.io) (Changing host)
20:23:24 tinwood joins (~tinwood@canonical/tinwood)
20:23:26 <ski> feetwind : .. ooh, now i think i see what you meant. you kinda wanted to declare a "submodule" as being exported from `Data.Text', is that right ?
20:23:59 johnw_ joins (~johnw@69.62.242.138)
20:24:22 <ski> (the module system in the MLs (SML,OCaml (but not F#)) allows such things, btw)
20:24:31 <ski> bwe : exactly ! :P
20:24:34 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
20:24:56 × johnw quits (~johnw@69.62.242.138) (Ping timeout: 245 seconds)
20:24:56 <ski> bwe : that's part of what i meant by "abstract it out of sight"
20:25:07 × fendor quits (~fendor@2a02:8388:1640:be00:2528:5dc7:a36e:9b87) (Remote host closed the connection)
20:25:10 <ski> so .. what's the type signature, now ?
20:25:24 <bwe> tickS :: State (Int, Int)
20:25:32 <ski> right
20:25:38 <ski> and implementation ?
20:25:42 <ski> er .. sorry
20:25:52 ski read too quickly
20:26:02 <ski> it's not `State (Int, Int)'
20:26:15 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Read error: Connection reset by peer)
20:26:17 × doyougnu- quits (~doyougnu@45.46.170.68) (Server closed connection)
20:26:18 <feetwind> yes basically, basically making Data.Text export a submodule that happens to share the name with the type Text -- since that's somewhat idiomatic anyway to do exactly that already like `import Data.Text (Text); import Data.Text qualified as Text`
20:26:29 <bwe> State (Int Int)
20:26:34 doyougnu joins (~doyougnu@45.46.170.68)
20:26:35 Square2 joins (~Square4@user/square)
20:26:38 <bwe> tickS :: State Int Int
20:26:43 <bwe> finally
20:27:13 <ski> tick :: Int -> (Int,Int) -- tickS :: State Int Int
20:27:15 <EvanR> bwe, on "State" being misleading, my running list of commonly used meanings for "state" is pretty long at this point
20:27:15 <ski> s -> (a ,s ) -- State s a
20:28:00 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
20:28:09 <EvanR> I guess haskell could have gone with Stateful for this type constructor
20:28:12 <ski> right, bwe. the first `Int' is the type of the state (which is both an implicit input and an implicit output). the second `Int' is the type of the result (which is only an output)
20:28:45 <ski> bwe : so .. how's `tickS' defined ?
20:29:02 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Remote host closed the connection)
20:32:42 ubert1 joins (~Thunderbi@178.165.182.252.wireless.dyn.drei.com)
20:32:56 × vilya quits (~vilya@user/vilya) (Ping timeout: 268 seconds)
20:33:07 <bwe> ski: -- looking up how I used State's value with Functor implementation
20:33:24 <ski> yup
20:33:27 vilya joins (~vilya@user/vilya)
20:33:42 × ubert quits (~Thunderbi@77.119.172.155.wireless.dyn.drei.com) (Ping timeout: 256 seconds)
20:33:42 ubert1 is now known as ubert
20:33:48 tromp joins (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
20:34:21 <bwe> tickS = State $ \s0 -> (s0, s0+1)
20:34:51 <bwe> now I understand my Functor implementation…why there is State $ \s0
20:35:42 <ski> right, that `s0' there is also the "hidden state input"
20:35:43 <bwe> I didn't understand where that s0 is coming from since. Now I get that the s0 is the first s from `s -> (a, s)`, it's the input state value
20:36:00 <ski> tickS = MkState (\n -> (n,n+1)) -- what i'd write
20:36:08 <ski> right
20:37:08 <ski> now .. if you *want* to, you could go on and insert calls to `tick' (not `tickS') in your existing `enumerateTree'/`enumerateTreeFrom' code (the explicit version, not using `State')
20:37:53 <ski> .. or, you could directly try to make the `State' version, and use `tickS' in that
20:40:33 dcoutts joins (~duncan@cpc69402-oxfd27-2-0-cust903.4-3.cable.virginm.net)
20:42:24 <bwe> ski: no, first the tick version
20:42:43 jmdaemon joins (~jmdaemon@user/jmdaemon)
20:43:16 <ski> ok, so the task then is to identify where to insert `tick', and which parts of the existing code it replaces
20:43:24 × sawilagar quits (~sawilagar@user/sawilagar) (Ping timeout: 246 seconds)
20:43:25 <bwe> I need to change the existing code so I can make use of (n, n+1) pattern
20:43:38 <ski> basically, yes
20:44:22 <ski> you could use `n0',`n1',`n2',`n3' for the numbered versions of the counter, and `n' for the "read out" reading that you're going to use as a label
20:44:47 <idgaen> that remembers me an example in "Programming in Haskell" by Graham Hutton :)
20:45:49 <ski> wouldn't be surprised if multiple people have come up with more or less the same example
20:45:50 machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net)
20:46:07 × aljazmc quits (~aljazmc@user/aljazmc) (Quit: Leaving)
20:50:43 <bwe> ski: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L63-L78 -- I've used prime to differentiate the names from each other
20:51:18 <bwe> ski: could you please confirm whether my change is correct? then I'd continue with State
20:51:55 <idgaen> i'm just amazed, anyway it's a good exercise
20:53:01 <ski> looks okay to me
20:53:05 <bwe> wow
20:53:28 <ski> oh, sorry, missed you changed `enumerateTree'
20:53:30 <ski> looking at that now
20:53:41 yangby joins (~secret@183.128.111.44)
20:54:10 <bwe> I wonder whether I should let that return only Tree (Int, a)
20:54:42 <bwe> (to only put State in enumerateTreeFrom)
20:54:47 <ski> right, you're not using n' in the `Postorder' case
20:55:36 <bwe> ski: I don't understand
20:55:38 <ski> otherwise, it looks okay (except i'd rename n1' to n' in the `Preorder' case, for consistency's sake)
20:55:53 <ski> let (n1, l') = enumerateTreeFrom n l
20:56:01 <ski> (n2, r') = enumerateTreeFrom n1 r
20:56:07 <ski> (n', n3) = tick n2
20:56:19 <ski> in (n3, Branch (n2, x) l' r')
20:56:26 <ski> note that n' is unused
20:56:33 <bwe> yes
20:56:56 <ski> in your other two cases, you're using both parts of the pair coming from `tick'
20:57:07 <bwe> that's right
20:57:24 <ski> so, you're not being consistent
20:58:12 <bwe> got it
20:58:18 <ski> (in the case of `Postorder', the case just above, it so *happens* that n' is equal to n2 .. but that's kinda a happy accident)
20:58:45 <bwe> ski: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L67-L68
20:59:25 <ski> ok, i guess that works, too
20:59:38 <ski> so, 'tickS' and `State' ?
20:59:50 <bwe> ooooh...
20:59:53 <EvanR> your inner enumerateTreeFrom branches on the TraversalOrder every time even though it doesn't change in the course of a call to enumerateTree. It could be turned inside out to only do that check at the beginning
20:59:58 eggplantade joins (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed)
21:00:16 <bwe> EvanR: cosmetics?
21:00:25 <ski> EvanR : yea, i noticed that before, but decided to not focus on that for the time being
21:01:11 <EvanR> I haven't met a haskell program I could not make cosmetically good xD
21:01:14 <ski> bwe : well, i guess it's kinda more about efficiency (constant factor)
21:01:58 <ski> (and yea, aesthetics is important)
21:02:07 <EvanR> otoh, would ghc fix this problem for you?
21:02:11 <ski> @quote not.optional
21:02:12 <lambdabot> O'Keefe says: "Elegance is not optional."
21:02:56 <bwe> ski: I could replace tick with tickS but I loose the argument now
21:03:04 <bwe> which is intended
21:03:22 <ski> you mean it's not as clear how to convert to using `State', now ?
21:03:28 <bwe> yes
21:03:32 <ski> right
21:04:38 <ski> so .. i guess, for the time being, the next step here may be a bit of the "oracle method" / "leap of faith"
21:05:33 <ski> perhaps you could at least suggest a version of `enumerateTreeFrom's type signature, that's using `State', rather than explicit state-passing/threading style (which is what your existing 'enumerateTreeFrom' is said to use)
21:05:37 <ski> ?
21:07:46 zetef joins (~quassel@95.77.17.251)
21:07:46 <bwe> I replace the counter value with the StateFUL
21:08:04 <bwe> enumerateTreeFrom :: State Int Int -> Tree a -> (_, Tree (Int, a))
21:09:09 <ski> remember the `State s a' is not the current state value, but the state *transformation*
21:09:55 santiagopim joins (~user@90.167.66.131)
21:10:02 <bwe> so it'd be enumerateTreeFrom :: s -> Tree a -> (Int, Tree (Int, a)) ?
21:10:22 <bwe> let me go one step back
21:10:27 <ski> .. it could perhaps be useful here to slightly refactor `enumerateTreeFrom' so that it (like `tick', and like inside `State s a'), the output state is the *second* part of the pair, not the first part
21:10:58 <ski> (this would also clean up your `let's in the definition, making them look more elegant)
21:11:07 <ski> @quote not.optional
21:11:07 <lambdabot> O'Keefe says: "Elegance is not optional."
21:14:02 <EvanR> States are programs that use a state, are waiting for an initial state before they can run
21:14:38 <int-e> EvanR: please no
21:14:45 <EvanR> lol
21:15:22 <EvanR> map is a function which takes functors xD
21:15:37 <bwe> ski: https://gist.github.com/benjaminweb/ea91583983f5eceb10549ed25db03ec4#file-monadt-hs-L54-L78
21:15:41 <int-e> :t fmap
21:15:42 <lambdabot> Functor f => (a -> b) -> f a -> f b
21:15:49 caryhartline joins (~caryhartl@168.182.58.169)
21:15:52 <EvanR> er, fmap
21:15:54 × caryhartline quits (~caryhartl@168.182.58.169) (Client Quit)
21:16:05 <int-e> EvanR: I'm sort of okay with that because I'm familiar with the dictionary passing implementation
21:16:22 <EvanR> it's so confused it's right
21:16:24 <int-e> So it's not confusing types and their values quite as much.
21:16:30 <bwe> ski: State (s -> (a, s))
21:17:03 <ski> bwe : yea, but `enumerateTreeFrom' is (currently) a bit off from that, since the output counter is the first part of the pair in `enumerateTreeFrom
21:17:05 <bwe> ski: (Tree (Int, a), Int)
21:17:08 <ski> ', not the second part
21:17:13 <ski> yesp
21:17:20 × jmdaemon quits (~jmdaemon@user/jmdaemon) (Ping timeout: 256 seconds)
21:17:42 <ski> (and with corresponding adaptations/refactoring of the definition of `enumerateTreeFrom')
21:19:41 <bwe> I am not following here
21:20:05 <ski> i mean, adapting
21:20:06 <ski> enumerateTreeFrom :: Int -> Tree a -> (Int, Tree (Int, a))
21:20:38 <ski> as you just indicated, you also need to adapt the definition accordingly
21:20:42 <ski> e.g.
21:20:46 <ski> (n1, l') = enumerateTreeFrom n l
21:20:47 <ski> becomes
21:20:55 <ski> (l', n1) = enumerateTreeFrom n l
21:21:04 <bwe> oh, pls refresh the gist
21:21:16 <bwe> rev 15
21:21:55 <ski> right
21:22:09 <ski> now notice how `n1',`n2',`n2' line up vertically, in the `let's
21:22:24 <bwe> yeah
21:22:25 <ski> (that's what i mean by "more elegant", here)
21:22:29 <bwe> true
21:22:43 × gehmehgeh quits (~user@user/gehmehgeh) (Quit: Leaving)
21:22:57 × zetef quits (~quassel@95.77.17.251) (Ping timeout: 246 seconds)
21:23:03 × oo_miguel quits (~Thunderbi@78-11-179-96.static.ip.netia.com.pl) (Quit: oo_miguel)
21:23:13 <k`> ski: (you must hate `foldr`)
21:23:24 <ski> how come ?
21:23:25 zetef joins (~quassel@5.2.182.98)
21:23:30 <k`> @t foldr
21:23:30 <lambdabot> Maybe you meant: tell thank you thanks thesaurus thx tic-tac-toe ticker time todo todo-add todo-delete type v @ ? .
21:23:35 <k`> @ty foldr
21:23:36 <lambdabot> Foldable t => (a -> b -> b) -> b -> t a -> b
21:23:51 <EvanR> @thanks
21:23:52 <lambdabot> you are welcome
21:23:58 <ski> you mean as opposed to `flip . foldr' ?
21:24:02 <mauke> :t y
21:24:03 <lambdabot> Expr
21:24:09 <bwe> ski: enumerateTreeFrom :: Int -> Tree a -> State (Tree (Int, a)) Int
21:24:18 <bwe> it's not finished :)
21:24:32 <bwe> but look how I've changed the return type
21:24:38 <ski> bwe, closish :)
21:24:40 <mauke> why are we taking in two trees?
21:24:58 × _ht quits (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) (Remote host closed the connection)
21:25:11 × ggVGc quits (~ggVGc@a.lowtech.earth) (Server closed connection)
21:25:23 <bwe> ski: how does the input Int change now?
21:25:26 <k`> ski: right
21:25:29 <ski> you agree with (previous version)
21:25:33 ggVGc joins (~ggVGc@a.lowtech.earth)
21:25:35 <bwe> oh, does it disappear?
21:25:38 <ski> enumerateTreeFrom :: Int -> Tree a -> (Tree (Int,a),Int)
21:25:39 <ski> yes ?
21:25:49 <bwe> like we did in the transition from tick to tickS???
21:25:52 <bwe> what??
21:25:52 jmdaemon joins (~jmdaemon@user/jmdaemon)
21:26:28 <ski> i mean, before switching to `State', i suggested putting the output state last, to conform with `tick' (and also with `State s a' being `s -> (a,s)')
21:27:09 × Inst quits (~Inst@120.244.192.250) (Ping timeout: 246 seconds)
21:27:26 <bwe> you mean first
21:27:38 <ski> no
21:27:50 emmanuelux joins (~emmanuelu@user/emmanuelux)
21:27:54 <bwe> enumerateTreeForm :: Tree a -> Int -> State (Tree (Int, a)) Int ?
21:28:07 <bwe> argh
21:28:10 <bwe> hold on
21:28:16 × k` quits (~user@152.7.255.206) (Remote host closed the connection)
21:28:21 <ski> (the second (output) `s' in `s -> (a,s)' is the last part of the pair)
21:29:13 <bwe> enumerateTreeFrom :: Tree a -> Int -> (Tree (Int, a)), Int)
21:29:25 <bwe> Int -> (Tree (Int, a)), Int)
21:29:38 <bwe> s -> (Tree (Int, a)), Int)
21:29:59 <bwe> s -> (a, s)
21:30:02 <ski> where does the second `s' go, in there ?
21:30:08 <ski> yah
21:30:12 <int-e> But the state is the first argument of `State s a`
21:30:12 <EvanR> fst and snd are so left-to-right-centric, shoulda used car and cdr
21:30:30 <int-e> So that'll be a bit confusinig at first.
21:30:38 <ski> EvanR : SML uses `#1' and `#2'
21:30:44 × takuan quits (~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection)
21:30:54 × danse-nr3 quits (~danse@151.43.130.136) (Ping timeout: 268 seconds)
21:31:06 <mauke> EvanR: that's unhaskellish
21:31:18 <int-e> EvanR: so which one is the address and which one is the data?
21:31:20 <mauke> contentsOfAddressPartOfRegister and contentsOfDataPartOfRegister
21:31:20 <EvanR> how about #1 and #0, just to make snd feel better xD, yes you're last, but you're also first in a way
21:31:40 <geekosaur> that looks more like java than haskell
21:32:10 <mauke> not my fault that haskell decided it wanted to look like java
21:32:17 <int-e> (The names "car" and "cdr" are so arcane. Though the resulting "caar" naming scheme is kind of cute.)
21:32:24 <ski> wouldn't the state seem more akin to address stuff ?
21:32:28 <EvanR> cdda
21:32:45 <mauke> my other car is a cdr
21:33:32 <EvanR> car and cdr are too arcane, but Monad is fine
21:33:36 × yangby quits (~secret@183.128.111.44) (Quit: Go out for a walk and buy a drink.)
21:33:42 <int-e> EvanR: you do know that "car" stands for "contents of address register", right?
21:34:04 <EvanR> in the 100th sublevel of my mind yes
21:34:25 <int-e> I'm okay with arcane names... but I wouldn't pretent that car and cdr are better than fst and snd.
21:34:31 <int-e> *pretend
21:34:45 <ski> now i'm wondering whether 680x0 got address vs. data registers from there
21:34:49 <EvanR> I wasn't being serious
21:35:02 <int-e> (ouch, ze german is shining srough)
21:35:24 <int-e> EvanR: really!
21:36:01 <bwe> ski: so I've got enumerateTreeFrom :: Tree a -> State (Tree (Int, a)) Int
21:36:06 <ski> iirc, Racket has `first' and `rest'
21:36:26 <ski> bwe : see what int-e said about `State s a'
21:37:02 <bwe> ski: got it
21:37:26 <ski> bwe : but yea, great that you realized that the `Int -> ' gets absorbed/abstracted into `State' :)
21:38:00 <ski> so .. taking int-e into account, what do you get ?
21:38:11 <bwe> enumerateTreeFrom :: Tree a -> State Int (Tree (Int, a))
21:38:15 int-e feels so used
21:38:15 <ski> right
21:38:22 <int-e> (scnr, carry on)
21:38:42 ski fills int-e's account
21:38:44 <bwe> ski: so `n` disappears as argument
21:38:48 <ski> yes
21:38:59 <ski> we want to hide the state/counter
21:39:11 <bwe> now enumerateTreeFrom returns State Int (Tree (Int, a))
21:39:17 <ski> right
21:39:25 <bwe> therefore (l', n1) = no longer works
21:39:47 <ski> so, now you must use either `>>=' or `do' (or, well, `<*>' could also work, i guess ..)
21:39:53 <ski> correct
21:40:03 eggplant_ joins (~Eggplanta@2600:1700:38c5:d800:30a6:1819:aaf8:7ae3)
21:40:11 <ski> if you write
21:40:43 <ski> t <- enumerateTreeFromS l
21:41:23 × sabino quits (~sabino@user/sabino) (Ping timeout: 268 seconds)
21:41:28 <ski> inside `do', then `enumerateTreeFromS l' is an `State Int (Tree (Int, a))' (as you said), and so `t' will become a `Tree (Int,a)' (since that's the "result type" part of the `State' .. the `a' in `State s a')
21:41:34 <ski> you could also write
21:41:43 <ski> enumerateTreeFromS l >>= \t ->
21:41:50 <ski> (and not use `do')
21:42:00 × eggplantade quits (~Eggplanta@2600:1700:38c5:d800:a1fe:14ba:659d:abed) (Ping timeout: 268 seconds)
21:42:10 <ski> (so, i guess, t here should be renamed to .. what ?)
21:42:19 sabino joins (~sabino@user/sabino)
21:42:40 <bwe> l'
21:42:50 <ski> yep :b
21:43:15 <ski> (i said `t' on purpose, to try to make you think about it)
21:43:19 <bwe> :)
21:44:00 <bwe> what about the tickS?
21:44:00 <ski> so, perhaps you've got *some* idea now for how to write at least *some* parts of `enumerateTreeFromS' ?
21:44:04 qqq joins (~qqq@92.43.167.61)
21:44:27 <ski> the input counter state disappears from sight. also the output counter state
21:44:41 <ski> (l',n1) = enumerateTreeFrom n l
21:44:46 <ski> became
21:44:56 <ski> l' <- enumerateTreeFromS l
21:44:57 <ski> and so
21:45:11 <ski> (n2',n3) = tick n2
21:45:15 <ski> becomes .. what ?
21:45:22 <bwe> n2' <- tickS
21:45:27 ski nods
21:45:47 <ski> then you'll need something to use instead of `in'
21:46:53 nate4 joins (~nate@c-98-45-158-125.hsd1.ca.comcast.net)
21:48:11 <bwe> that will be return I suspect
21:48:19 <bwe> the let becomes do
21:48:27 <ski> try it ?
21:48:53 <ski> (you'll also need to do something about the initial call, in the wrapper)
21:49:35 <ski> it might be helpful to define a helper function, for extracting out the state transformation function inside a `State s a'
21:50:55 <ski> (otherwise you'll need to use `case' or `let' for this, in `enumerateTree', for the initial invocation of `enumerateTreeFromS' .. well, at least if you want to *keep* the present type signature of `enumerateTree')
21:51:24 <bwe> ski:
21:51:54 <bwe> ski: the enumerateTreeFrom part compiles now, let me think of what to do about the enumerateTree
21:52:28 × nate4 quits (~nate@c-98-45-158-125.hsd1.ca.comcast.net) (Ping timeout: 256 seconds)
21:52:41 <bwe> ski: I need to define it in the State ...
21:52:51 <ski> "it" referring to ?
21:53:10 <bwe> the helper function extracting the state transformation function inside State s a
21:54:11 <ski> yea, the helper/worker, `enumerateTreeFromS', is in `State'
21:55:09 <bwe> newtype State s a = MkState { runState :: s -> (a,s) } ?
21:55:51 <ski> sure, that would work
21:56:06 <EvanR> that's a good looking newtype if I ever seen one
21:56:11 × totbwf quits (sid402332@id-402332.uxbridge.irccloud.com) (Server closed connection)
21:56:19 totbwf joins (sid402332@id-402332.uxbridge.irccloud.com)
21:58:53 Hooloovoo joins (~Hooloovoo@hax0rbana.org)
21:59:46 × ec quits (~ec@gateway/tor-sasl/ec) (Remote host closed the connection)
22:00:13 ec joins (~ec@gateway/tor-sasl/ec)
22:04:01 <EvanR> that field notation was confusing to me at first, since really runState :: State s a -> s -> (a,s), directly contradicting that notation
22:04:15 CiaoSen joins (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5)
22:05:16 <ski> yea. imho, SML got the field extraction better
22:05:29 × drlkf quits (~drlkf@192.184.163.34.bc.googleusercontent.com) (Server closed connection)
22:05:35 <ski> if `x' is a field, then `#x' is the function that extracts that field
22:05:52 <EvanR> which I now know we can emulate with enough extensions and stuff
22:05:53 <ski> (this is one of the warts in Haskell, imho)
22:05:54 drlkf joins (~drlkf@192.184.163.34.bc.googleusercontent.com)
22:06:37 <ski> (and tuples are just records whose field names are consecutive integers counting up .. unfortunately from one, not from zero)
22:07:18 <EvanR> oh, you can use #1 with (a,b) and (a,b,c)?
22:07:25 <ski> note that punning of field names is less useful, due to this unfortunate reuse of the same name for the extraction function
22:07:29 <ski> yes
22:07:36 <EvanR> wicked
22:10:21 <ski> (the types are called `a * b' resp. `a * b * c', though (and those are really `{0 : a,1 : b}' resp. `{0 : a,1 : b,2 : c}') .. another misdesign in Haskell, noticable with `DataKinds' and also with attempts to add dependent types. what if i want to define a *type* having a parameter which is a tuple (not a tuple type) of types ?)
22:11:58 <ski> (having type parameters be records of types would also be handy for certain situations .. if all the types have the same kind you can express it differently, via a GADT indexed by a `data' type enumerating the record fields)
22:12:20 ski looks at bwe
22:12:50 × eggplant_ quits (~Eggplanta@2600:1700:38c5:d800:30a6:1819:aaf8:7ae3) (Ping timeout: 268 seconds)
22:13:14 <ski> (well, i should say, if all those types are `data' types over which definition you have control)
22:13:20 <bwe> ski: hm, I need to initialise the state with 0
22:13:25 <ski> right
22:13:32 sawilagar joins (~sawilagar@user/sawilagar)
22:13:41 <ski> so `runState' will extract the state transformation function for you
22:13:50 <ski> then you just need to pass in the initial state
22:14:01 <bwe> runState 0
22:14:11 <ski> here you get
22:14:21 <ski> runState :: State s a -> (s -> (a,s))
22:14:24 <ski> or, if you prefer
22:14:28 <ski> runState :: State s a -> s -> (a,s)
22:16:01 <ski> (so not `runState 0', but .. ?)
22:16:25 Pickchea joins (~private@user/pickchea)
22:17:51 <bwe> MkState 0
22:18:04 <bwe> runState (MkState 0)
22:18:32 <bwe> let me type hole that
22:18:50 <ski> what's the top invocation that you want to pass of the initial state to ?
22:19:05 <bwe> runState _ >>= enumerateTreeFrom
22:19:18 <bwe> Found hole: _ :: State s0 a1
22:19:44 <ski> what's the type of `enumerateTreeFromS' ?
22:20:01 <bwe> Tree a -> State Int (Tree (Int, a))
22:20:29 <ski> so, how do you invoke it ?
22:20:41 <ski> (in `enumerateTree')
22:21:50 <bwe> I need to put in the abstraction that abstracts away the counter
22:22:30 arahael joins (~arahael@119-18-2-212.771202.syd.nbn.aussiebb.net)
22:22:49 <bwe> wait
22:22:57 <ski> well, if `enumerateTreeFromS' is a function (of type `Tree a -> State Int (Tree (Int, a))') you probably should pass it an argument, at least, right ?
22:24:58 × michalz quits (~michalz@185.246.207.193) (Remote host closed the connection)
22:25:57 <bwe> I should give it Tree a
22:26:22 <ski> yes. which tree ?
22:26:41 <bwe> well the original input
22:26:44 <ski> yes
22:27:02 <ski> dunno what you call that .. let's say `t'
22:27:17 <ski> so, you then have `enumerateTreeFromS t', which has type `State Int (Tree (Int, a))'
22:27:29 <ski> what do you do know, to *use* this result ?
22:27:33 <ski> s/know/now/
22:28:21 <bwe> enumerateTree order t = runState (enumerateTreeFrom t) 0
22:28:23 <ski> well .. you do want to get the labelled tree "out" somehow right ?
22:28:32 <ski> yep !
22:28:50 <ski> sometimes, i'd spell that as
22:28:56 <bwe> I still don't comprehend that but let me think that through the other day
22:29:03 <ski> enumerateTree order t = enumerateTreeFrom t `runState` 0
22:29:10 <ski> but that's more a matter of taste thing
22:29:10 × tromp quits (~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
22:29:30 <ski> `runState' supplies the "hidden state input", giving you back the pair of the result and the hidden state output
22:29:43 <ski> right
22:29:57 <ski> bwe : does the code type-check now ?
22:30:12 <bwe> yup
22:30:16 <ski> does it work ?
22:30:26 <ski> (at least for my given example tree, say ?)
22:32:36 × qqq quits (~qqq@92.43.167.61) (Ping timeout: 246 seconds)
22:36:09 <bwe> no, it fails with No instance nor default method for class operation pure
22:37:00 <ski> ah, right. you didn't define `return'
22:37:19 <bwe> where?
22:37:30 <ski> (nor `pure' in `Applicative' .. they're the same operation, have different names because of hysterical raisins)
22:37:32 <bwe> I need to leave now unfortunately
22:37:51 <ski> in `instance Monad (State s) where ...'
22:38:16 <ski> `return' is supposed to "do nothing, apart from just giving back the argument as result", btw
22:38:29 <ski> return :: a -> State s a
22:38:31 <ski> in your case
22:38:54 <ski> bwe : yea, i hope this has helped at least some
22:39:13 <bwe> quite a lot
22:39:22 <bwe> I enjoyed it very much
22:39:36 <bwe> ski: thank you very much
22:39:49 qqq joins (~qqq@92.43.167.61)
22:39:54 <ski> yw
22:39:54 <bwe> ski: care if we continue where we left another time?
22:39:57 ski bows
22:40:00 <ski> sure
22:40:14 <bwe> awesome :)
22:41:31 × acidjnk quits (~acidjnk@p200300d6e72b9310fd221caae09ed082.dip0.t-ipconnect.de) (Ping timeout: 268 seconds)
22:43:52 Guest|66 joins (~Guest|66@73.110.126.92)
22:44:36 × qqq quits (~qqq@92.43.167.61) (Ping timeout: 256 seconds)
22:44:48 × trev quits (~trev@user/trev) (Quit: trev)
22:45:30 qqq joins (~qqq@92.43.167.61)
22:47:45 × edmundnoble_ quits (sid229620@id-229620.helmsley.irccloud.com) (Server closed connection)
22:47:54 edmundnoble_ joins (sid229620@id-229620.helmsley.irccloud.com)
22:49:05 × statusbot quits (~statusbot@ec2-34-198-122-184.compute-1.amazonaws.com) (Remote host closed the connection)
22:49:08 × Jackneill quits (~Jackneill@20014C4E1E1AA200A8C1C5D762EA8C40.dsl.pool.telekom.hu) (Ping timeout: 256 seconds)
22:49:18 statusbot joins (~statusbot@ec2-34-198-122-184.compute-1.amazonaws.com)
22:49:44 × Guest|66 quits (~Guest|66@73.110.126.92) (Quit: Connection closed)
22:49:45 wroathe joins (~wroathe@50.205.197.50)
22:49:45 × wroathe quits (~wroathe@50.205.197.50) (Changing host)
22:49:45 wroathe joins (~wroathe@user/wroathe)
22:50:14 <dibblego> Does this function exist anywhere? readerState :: Functor f => ReaderT r f a -> StateT r f a; readerState (ReaderT r) = StateT (\s -> fmap (\a -> (a, s)) (r s))
22:51:11 <ski> not that i know (but i've played around with it, and related things, privately, before)
22:51:21 thegeekinside joins (~thegeekin@189.180.53.210)
22:51:55 <Axman6> feels related to local, at least in intent
22:52:10 <ski> (we have two monads, with one being embeddable inside the other, more or less. we get stuff like `m a -> (a -> n b) -> n b')
22:52:29 <dibblego> it could half-nicer with something :: MonadState s f => (s -> f a) -> f a
22:53:55 × sabino quits (~sabino@user/sabino) (Quit: Lambda _ -> x)
22:54:43 <ski> (`m' can be `Reader rs' and `n' be `State rs'. or `m' can be `Maybe' and `n' be `[]' ..)
22:55:21 <ski> dibblego : hm, not seeing how `something' is comparable ?
22:55:37 <dibblego> would just be slightly nicer to write
22:56:43 Sgeo joins (~Sgeo@user/sgeo)
22:56:48 <ski> `readerState' copies over the current state as the resulting state. `something' just read the state, no ?
22:57:08 <ski> (kinda like `asks')
22:57:38 <probie> :t (&&& returnA)
22:57:39 <lambdabot> Arrow a => a c' c -> a c' (c, c')
22:58:13 acidjnk joins (~acidjnk@p200300d6e72b93446103f524bf4ee276.dip0.t-ipconnect.de)
22:58:30 <ski> @type sized
22:58:31 <lambdabot> (Int -> Gen a) -> Gen a
22:58:37 × johnw_ quits (~johnw@69.62.242.138) (Quit: ZNC - http://znc.in)
23:00:21 <dibblego> readerState :: MonadState r f => ReaderT r f b -> f b; readerState r = get >>= runReaderT r
23:01:56 <EvanR> at that point... you could just write "get >>= runReaderT r"
23:02:21 × jmdaemon quits (~jmdaemon@user/jmdaemon) (Ping timeout: 246 seconds)
23:03:46 <EvanR> and it would be obvious what it does
23:03:51 <dibblego> agree
23:04:48 <dibblego> wait, that's not quite right
23:05:26 <ski> `fmap', i guess
23:06:30 <ski> hm, right, that's `ReaderT', not `Reader'. so `lift' ?
23:07:01 <ski> @type \r -> lift . runReaderT r =<< get
23:07:03 <lambdabot> (MonadTrans t, Monad m, MonadState r (t m)) => ReaderT r m b -> t m b
23:07:06 × coot quits (~coot@89-69-206-216.dynamic.chello.pl) (Quit: coot)
23:07:44 coot joins (~coot@89.69.206.216)
23:09:13 <probie> readerState :: Monad f => ReaderT r f a -> StateT r f a; readerState = coerce . (&&& returnA) . Kleisli . runReader
23:10:09 jmdaemon joins (~jmdaemon@user/jmdaemon)
23:10:11 × chomwitt quits (~chomwitt@ppp-94-67-217-242.home.otenet.gr) (Ping timeout: 268 seconds)
23:11:23 [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470)
23:12:27 <EvanR> ski and probie came to the conclusion f needed to be a Monad
23:13:53 × santiagopim quits (~user@90.167.66.131) (Ping timeout: 268 seconds)
23:14:16 <EvanR> does it ?
23:14:22 <ski> @type \(ReaderT f) -> StateT (\s -> (,s) <$> f s)
23:14:23 <lambdabot> Functor m => ReaderT r m a -> StateT r m a
23:14:27 <ski> (did we ?)
23:14:50 <EvanR> well the type sigs don't liez1
23:14:55 <EvanR> !
23:15:07 × [_] quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 268 seconds)
23:15:14 <ski> dibblego's original seems fine, to me
23:15:17 <probie> I needed it to be a monad because I wanted to pretend Arrow is somehow still relevant
23:15:28 <EvanR> lol
23:15:55 ski was just trying to fix the `get >>= runReaderT r' one (which obviously already presupposed `Monad')
23:18:30 vilya_ joins (~vilya@user/vilya)
23:18:49 <EvanR> it's cool that this operation involving 2 monad transformers doesn't require an underlying monad
23:18:49 × vilya quits (~vilya@user/vilya) (Ping timeout: 268 seconds)
23:19:47 <EvanR> this is why happens when type systems are actually reasonable
23:19:50 <EvanR> what*
23:21:29 <probie> Is it that surprising? You're just turning `a -> m b` to `a -> m (b, a)`
23:21:53 <EvanR> also, the scheme semantics are apparently written in haskell... or perhaps agda https://i.imgur.com/YpEJfY4.png
23:21:54 × misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 268 seconds)
23:22:40 × coot quits (~coot@89.69.206.216) (Quit: coot)
23:23:44 <EvanR> in lisp their code looks like data. In haskell our code looks like semantics
23:25:23 <ski> denotational semantics
23:26:45 caryhartline joins (~caryhartl@168.182.58.169)
23:31:38 × wroathe quits (~wroathe@user/wroathe) (Ping timeout: 256 seconds)
23:36:10 × mechap quits (~mechap@user/mechap) (Ping timeout: 256 seconds)
23:37:52 × stiell quits (~stiell@gateway/tor-sasl/stiell) (Ping timeout: 264 seconds)
23:38:34 × idgaen quits (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) (Quit: WeeChat 4.1.1)
23:38:58 × tremon quits (~tremon@83.80.159.219) (Quit: getting boxed in)
23:39:31 × Pickchea quits (~private@user/pickchea) (Quit: Leaving)
23:39:34 <ski> @type state . runState
23:39:35 <lambdabot> MonadState s m => State s a -> m a
23:39:40 <ski> something along the lines of `forall a. MonadStateT t s m n => t (StateT s m) a -> n a', and `forall a. MonadStateT t s m n => n a -> t (StateT s m) a', could perhaps be useful
23:42:57 × hueso quits (~root@user/hueso) (Quit: hueso)
23:46:19 hueso joins (~root@user/hueso)
23:50:52 × hueso quits (~root@user/hueso) (Client Quit)
23:53:27 × zetef quits (~quassel@5.2.182.98) (Ping timeout: 246 seconds)
23:53:55 falafel_ joins (~falafel@62.175.113.194.dyn.user.ono.com)
23:53:57 <EvanR> I heard you like State, so I put a StateT in your MonadStateT
23:53:59 × megaTherion quits (~therion@unix.io) (Server closed connection)
23:54:07 hueso joins (~root@user/hueso)
23:54:13 megaTherion joins (~therion@unix.io)
23:55:50 <monochrom> "state of the onion" >:)
23:56:34 <EvanR> er where is MonadStateT defined
23:56:47 <monochrom> There is none. There is only MonadState.
23:57:24 <monochrom> But you can just go with "I put a StateT in your MonadState". :)
23:57:50 × CiaoSen quits (~Jura@2a05:5800:289:5000:2a3a:4dff:fe84:dbd5) (Ping timeout: 245 seconds)
23:58:15 × Tuplanolla quits (~Tuplanoll@91-159-68-236.elisa-laajakaista.fi) (Quit: Leaving.)
23:58:16 × falafel_ quits (~falafel@62.175.113.194.dyn.user.ono.com) (Ping timeout: 256 seconds)

All times are in UTC on 2023-11-15.