2022/12/07

2022-12-07 00:04:59 +0100waleee(~waleee@h-176-10-137-138.NA.cust.bahnhof.se) (Ping timeout: 264 seconds)
2022-12-07 00:05:00 +0100christiansen(~christian@83-95-137-75-dynamic.dk.customer.tdc.net) (Ping timeout: 256 seconds)
2022-12-07 00:07:41 +0100crazazy`(~user@130.89.173.127)
2022-12-07 00:09:39 +0100crazazy(~user@mobiela8a1593778d7.roaming.utwente.nl) (Ping timeout: 260 seconds)
2022-12-07 00:09:45 +0100crazazy`(~user@130.89.173.127) (Remote host closed the connection)
2022-12-07 00:17:38 +0100 <iqubic> tomsmeding: What ae you trying to do?
2022-12-07 00:18:53 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt)
2022-12-07 00:19:35 +0100Tuplanolla(~Tuplanoll@91-159-68-152.elisa-laajakaista.fi) (Quit: Leaving.)
2022-12-07 00:21:02 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 268 seconds)
2022-12-07 00:25:31 +0100gurkenglas(~gurkengla@p548ac72e.dip0.t-ipconnect.de)
2022-12-07 00:26:08 +0100 <iqubic> s/ae/are/
2022-12-07 00:28:06 +0100waleee(~waleee@h-176-10-137-138.NA.cust.bahnhof.se)
2022-12-07 00:31:01 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 00:32:24 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net)
2022-12-07 00:32:32 +0100 <dsal> ær
2022-12-07 00:32:32 +0100masterbuilder(~master@user/masterbuilder)
2022-12-07 00:33:01 +0100kenaryn(~aurele@cre71-h03-89-88-44-27.dsl.sta.abo.bbox.fr) (Quit: leaving)
2022-12-07 00:34:26 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Remote host closed the connection)
2022-12-07 00:35:50 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 268 seconds)
2022-12-07 00:36:39 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 00:45:25 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 00:45:40 +0100hippoid(~idris@user/hippoid) (Quit: WeeChat 3.5)
2022-12-07 00:46:07 +0100mestre(~mestre@191.177.185.178) (Quit: Lost terminal)
2022-12-07 00:46:30 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 00:46:43 +0100hippoid(~idris@user/hippoid)
2022-12-07 00:49:33 +0100aliosablack(~chomwitt@2a02:587:7a0c:6a00:1ac0:4dff:fedb:a3f1) (Ping timeout: 260 seconds)
2022-12-07 00:49:36 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 00:49:46 +0100acidjnk_new(~acidjnk@p200300d6e7137a665d3a2af2e35b2922.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
2022-12-07 00:50:44 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 00:51:25 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 260 seconds)
2022-12-07 00:59:33 +0100opticblast(~Thunderbi@secure-165.caltech.edu)
2022-12-07 01:12:11 +0100opticblast(~Thunderbi@secure-165.caltech.edu) (Ping timeout: 264 seconds)
2022-12-07 01:13:30 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 01:17:54 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 260 seconds)
2022-12-07 01:21:07 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 01:24:37 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 01:28:55 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 252 seconds)
2022-12-07 01:35:39 +0100bjourne2(~bjorn@94.191.136.201.mobile.tre.se) (Read error: Connection reset by peer)
2022-12-07 01:41:22 +0100Erutuon(~Erutuon@user/erutuon)
2022-12-07 01:42:56 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 01:47:34 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 256 seconds)
2022-12-07 01:50:04 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:2d36:9da8:a662:60e2) (Remote host closed the connection)
2022-12-07 01:50:22 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:2d36:9da8:a662:60e2)
2022-12-07 01:51:32 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 256 seconds)
2022-12-07 02:02:10 +0100Kaiepi(~Kaiepi@108.175.84.104) (Ping timeout: 268 seconds)
2022-12-07 02:06:08 +0100 <Axman6> Anyone else ever wanted pattern predicates? like, partitrion (\is Head{}; Body{}; Div{class = ""}) Writing (\case Head{} -> True; Body{} -> True; Div{class = ""} -> True; _ False) is so tedious
2022-12-07 02:06:15 +0100 <Axman6> partition*
2022-12-07 02:07:58 +0100 <dsal> lens probably has something for that.
2022-12-07 02:08:31 +0100use-value1(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6)
2022-12-07 02:08:59 +0100 <Axman6> yeah you can do something like has (_Head <> _Body <> _Div) I think - not sure how you'd do the field check too, but it's also not relevant fo what I'm doing
2022-12-07 02:10:17 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307)
2022-12-07 02:10:17 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
2022-12-07 02:10:23 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:2d36:9da8:a662:60e2) (Ping timeout: 264 seconds)
2022-12-07 02:10:23 +0100use-value1use-value
2022-12-07 02:14:42 +0100xff0x(~xff0x@2405:6580:b080:900:f990:42a1:d746:59a8) (Ping timeout: 252 seconds)
2022-12-07 02:14:50 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307) (Ping timeout: 260 seconds)
2022-12-07 02:14:56 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 02:15:35 +0100king_gs(~Thunderbi@187.201.204.122) (Client Quit)
2022-12-07 02:15:53 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 02:16:24 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8)
2022-12-07 02:17:25 +0100AWizzArd(~code@gehrels.uberspace.de) (Ping timeout: 256 seconds)
2022-12-07 02:17:31 +0100noctux(~noctux@user/noctux) (Ping timeout: 248 seconds)
2022-12-07 02:17:31 +0100AWizzArd(~code@gehrels.uberspace.de)
2022-12-07 02:17:51 +0100mjacob(~mjacob@adrastea.uberspace.de) (Ping timeout: 260 seconds)
2022-12-07 02:17:56 +0100noctux(~noctux@user/noctux)
2022-12-07 02:18:32 +0100wroathe(~wroathe@207-153-38-140.fttp.usinternet.com)
2022-12-07 02:18:32 +0100wroathe(~wroathe@207-153-38-140.fttp.usinternet.com) (Changing host)
2022-12-07 02:18:32 +0100wroathe(~wroathe@user/wroathe)
2022-12-07 02:19:28 +0100 <zzz> h
2022-12-07 02:19:30 +0100mjacob(~mjacob@adrastea.uberspace.de)
2022-12-07 02:26:26 +0100Lumia(~Lumia@user/Lumia)
2022-12-07 02:26:30 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Quit: WeeChat 3.7.1)
2022-12-07 02:27:27 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net)
2022-12-07 02:27:38 +0100 <[Leary]> gurkenglas: I thought this last time you asked this question, but maybe you're looking for one of the `improve`s? E.g. https://hackage.haskell.org/package/kan-extensions-5.2.5/docs/Control-Monad-Codensity.html#v:improve
2022-12-07 02:34:37 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua) (Ping timeout: 252 seconds)
2022-12-07 02:37:41 +0100razetime(~quassel@49.207.203.213)
2022-12-07 02:42:47 +0100zant(~zant@62.214.20.26) (Ping timeout: 264 seconds)
2022-12-07 02:43:04 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 260 seconds)
2022-12-07 02:50:04 +0100tomokojun(~tomokojun@static-198-54-130-102.cust.tzulo.com) (Ping timeout: 260 seconds)
2022-12-07 02:50:39 +0100gurkenglas(~gurkengla@p548ac72e.dip0.t-ipconnect.de) (Ping timeout: 260 seconds)
2022-12-07 02:50:42 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 02:55:02 +0100king_gs1(~Thunderbi@2806:103e:29:94a4:81e0:429b:22ec:cf13)
2022-12-07 02:55:03 +0100king_gs(~Thunderbi@187.201.204.122) (Read error: Connection reset by peer)
2022-12-07 02:55:03 +0100king_gs1king_gs
2022-12-07 02:59:58 +0100sagax(~sagax_nb@user/sagax)
2022-12-07 03:02:54 +0100xff0x(~xff0x@125x103x176x34.ap125.ftth.ucom.ne.jp)
2022-12-07 03:05:07 +0100Lumia(~Lumia@user/Lumia) (Quit: ,-)
2022-12-07 03:07:01 +0100bontaq(~user@ool-45779fe5.dyn.optonline.net)
2022-12-07 03:09:56 +0100jao(~jao@cpc103048-sgyl39-2-0-cust502.18-2.cable.virginm.net) (Ping timeout: 248 seconds)
2022-12-07 03:16:52 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex) (Remote host closed the connection)
2022-12-07 03:16:52 +0100chexum(~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection)
2022-12-07 03:16:52 +0100califax(~califax@user/califx) (Remote host closed the connection)
2022-12-07 03:16:55 +0100FinnElija(~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
2022-12-07 03:16:55 +0100ec_(~ec@gateway/tor-sasl/ec) (Remote host closed the connection)
2022-12-07 03:16:55 +0100azimut(~azimut@gateway/tor-sasl/azimut) (Remote host closed the connection)
2022-12-07 03:16:55 +0100jpds1(~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection)
2022-12-07 03:17:21 +0100jpds1(~jpds@gateway/tor-sasl/jpds)
2022-12-07 03:17:33 +0100chexum(~quassel@gateway/tor-sasl/chexum)
2022-12-07 03:17:36 +0100ec_(~ec@gateway/tor-sasl/ec)
2022-12-07 03:17:57 +0100FinnElija(~finn_elij@user/finn-elija/x-0085643)
2022-12-07 03:17:58 +0100azimut(~azimut@gateway/tor-sasl/azimut)
2022-12-07 03:18:08 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex)
2022-12-07 03:20:54 +0100califax(~califax@user/califx)
2022-12-07 03:21:58 +0100zant(~zant@62.214.20.26)
2022-12-07 03:22:23 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 264 seconds)
2022-12-07 03:26:28 +0100zant(~zant@62.214.20.26) (Ping timeout: 248 seconds)
2022-12-07 03:28:29 +0100chexum(~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection)
2022-12-07 03:28:50 +0100chexum(~quassel@gateway/tor-sasl/chexum)
2022-12-07 03:33:11 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0)
2022-12-07 03:38:27 +0100ddellacosta(~ddellacos@static-198-44-136-91.cust.tzulo.com) (Ping timeout: 256 seconds)
2022-12-07 03:40:31 +0100ddellacosta(~ddellacos@static-198-44-136-134.cust.tzulo.com)
2022-12-07 03:42:04 +0100Erutuon(~Erutuon@user/erutuon) (Ping timeout: 268 seconds)
2022-12-07 03:42:47 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt) (Ping timeout: 264 seconds)
2022-12-07 03:50:07 +0100Unicorn_Princess(~Unicorn_P@user/Unicorn-Princess/x-3540542) (Remote host closed the connection)
2022-12-07 03:50:58 +0100money_(~money@user/polo) (Quit: money_)
2022-12-07 03:51:44 +0100 <Chai-T-Rex> How can I install the `split` package for the generic `ghci` command?
2022-12-07 03:53:24 +0100 <Chai-T-Rex> Or, alternatively, how can I install it so that I can use some command line options to GHCi?
2022-12-07 03:53:51 +0100 <c_wraith> are you comfortable using something like `cabal repl -b split` instead?
2022-12-07 03:54:22 +0100 <Chai-T-Rex> As long as it reads `.ghc/ghci.conf`.
2022-12-07 03:54:48 +0100Lumia(~Lumia@user/Lumia)
2022-12-07 03:56:28 +0100 <Chai-T-Rex> When I do that, it can't find the `array` package included with GHC.
2022-12-07 03:58:04 +0100 <Chai-T-Rex> It also seems to delete some functions I'd defined in GHCi.conf.
2022-12-07 04:01:08 +0100 <Chai-T-Rex> I found out that the unrecommended `cabal install --reinstall -O2 --lib split` works.
2022-12-07 04:01:22 +0100jero98772(~jero98772@2800:484:1d80:d8ce:efcc:cbb3:7f2a:6dff) (Remote host closed the connection)
2022-12-07 04:08:08 +0100 <sm> chatgpt, compose me a command line to do haskell thing I want
2022-12-07 04:09:22 +0100 <sm> heh. It says: ghci -package split -ghci-script ~/.ghc/ghci.conf
2022-12-07 04:10:38 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6) (Remote host closed the connection)
2022-12-07 04:10:57 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6)
2022-12-07 04:11:43 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307)
2022-12-07 04:13:23 +0100mmhat(~mmh@p200300f1c73b5136ee086bfffe095315.dip0.t-ipconnect.de) (Quit: WeeChat 3.7.1)
2022-12-07 04:13:48 +0100Topsi(~Topsi@dyndsl-095-033-034-215.ewe-ip-backbone.de) (Read error: Connection reset by peer)
2022-12-07 04:15:51 +0100bobbingbob(~dfadsva@2604:3d09:207f:f650::7b3a) (Ping timeout: 256 seconds)
2022-12-07 04:16:10 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307) (Ping timeout: 260 seconds)
2022-12-07 04:16:56 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 04:17:38 +0100causal(~user@50.35.85.7) (Quit: WeeChat 3.7.1)
2022-12-07 04:18:10 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 04:18:42 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0) (Remote host closed the connection)
2022-12-07 04:22:37 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0)
2022-12-07 04:27:56 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Ping timeout: 255 seconds)
2022-12-07 04:28:45 +0100DigitalKiwi(~kiwi@2604:a880:400:d0::1ca0:e001) (Quit: quite.)
2022-12-07 04:29:32 +0100DigitalKiwi(~kiwi@2604:a880:400:d0::1ca0:e001)
2022-12-07 04:30:47 +0100machinedgod(~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 268 seconds)
2022-12-07 04:30:59 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 04:36:54 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua)
2022-12-07 04:43:26 +0100instantaphex(~jb@c-73-171-252-84.hsd1.fl.comcast.net)
2022-12-07 04:45:20 +0100td_(~td@83.135.9.33) (Ping timeout: 260 seconds)
2022-12-07 04:45:30 +0100Lumia(~Lumia@user/Lumia) (Ping timeout: 256 seconds)
2022-12-07 04:46:42 +0100td_(~td@83.135.9.15)
2022-12-07 04:46:43 +0100gentauro(~gentauro@user/gentauro) (Read error: Connection reset by peer)
2022-12-07 04:47:21 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 04:47:35 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307)
2022-12-07 04:52:20 +0100sloorush(~sloorush@52.187.184.81) (Ping timeout: 248 seconds)
2022-12-07 04:52:27 +0100gentauro(~gentauro@user/gentauro)
2022-12-07 04:52:52 +0100sloorush(~sloorush@52.187.184.81)
2022-12-07 04:55:04 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 04:55:04 +0100chexum(~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection)
2022-12-07 04:55:04 +0100ec_(~ec@gateway/tor-sasl/ec) (Remote host closed the connection)
2022-12-07 04:55:04 +0100FinnElija(~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection)
2022-12-07 04:55:53 +0100chexum(~quassel@gateway/tor-sasl/chexum)
2022-12-07 04:56:11 +0100FinnElija(~finn_elij@user/finn-elija/x-0085643)
2022-12-07 04:56:17 +0100ec_(~ec@gateway/tor-sasl/ec)
2022-12-07 04:57:30 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 05:02:59 +0100euandreh(~Thunderbi@179.214.113.107)
2022-12-07 05:04:51 +0100lisbeths(uid135845@id-135845.lymington.irccloud.com)
2022-12-07 05:05:45 +0100euandreh(~Thunderbi@179.214.113.107) (Remote host closed the connection)
2022-12-07 05:06:26 +0100048AAH6AD(~Thunderbi@179.214.113.107)
2022-12-07 05:16:13 +0100 <albet70> write a module, where the module file should be for import? is there an environment variable for the module path?
2022-12-07 05:16:43 +0100 <albet70> what's the path 'import' will seek?
2022-12-07 05:17:45 +0100 <sclv> without any additional flags to ghc or any cabal file it uses the cwd as the base
2022-12-07 05:18:05 +0100Lumia(~Lumia@user/Lumia)
2022-12-07 05:19:39 +0100 <albet70> where cwd point?
2022-12-07 05:19:46 +0100wroathe(~wroathe@user/wroathe) (Quit: leaving)
2022-12-07 05:22:05 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 260 seconds)
2022-12-07 05:22:27 +0100 <albet70> why it wouldn't import those custom modules where are on the same path with the caller?
2022-12-07 05:23:40 +0100 <sm> @where paste, albet70
2022-12-07 05:23:40 +0100 <lambdabot> I know nothing about paste,.
2022-12-07 05:23:50 +0100motherfsck(~motherfsc@user/motherfsck) (Ping timeout: 260 seconds)
2022-12-07 05:24:44 +0100 <sm> @where paste
2022-12-07 05:24:44 +0100 <lambdabot> Help us help you: please paste full code, input and/or output at e.g. https://paste.tomsmeding.com
2022-12-07 05:25:57 +0100 <albet70> sm https://paste.tomsmeding.com/nusGwMZC
2022-12-07 05:26:29 +0100mbuf(~Shakthi@49.204.118.69)
2022-12-07 05:29:05 +0100freeside_(~mengwong@103.252.202.193) (Ping timeout: 260 seconds)
2022-12-07 05:29:08 +0100freeside(~mengwong@103.252.202.193) (Ping timeout: 248 seconds)
2022-12-07 05:30:33 +0100shriekingnoise_(~shrieking@186.137.167.202) (Quit: Quit)
2022-12-07 05:32:50 +0100 <dsal> albet70: Custom.hs
2022-12-07 05:33:05 +0100 <dsal> Doing this without a project is kind of hard mode, though.
2022-12-07 05:33:07 +0100 <dsal> Same for Chai-T-Rex
2022-12-07 05:36:41 +0100 <EvanR> imagine if you needed a project to run a bash script
2022-12-07 05:37:06 +0100 <EvanR> actually maybe that's a workable discriminator for "scripting"
2022-12-07 05:37:27 +0100Lumia(~Lumia@user/Lumia) (Ping timeout: 256 seconds)
2022-12-07 05:39:08 +0100motherfsck(~motherfsc@user/motherfsck)
2022-12-07 05:39:29 +0100 <dsal> Also, you quite often *do*.
2022-12-07 05:40:02 +0100 <dsal> Usually that project is shell.nix for me, but before nix it was "make sure you have whatever your operating system calls these packages before you try to run this script"
2022-12-07 05:40:34 +0100 <EvanR> ok that's a dependency, not a build system or dependency management system
2022-12-07 05:40:45 +0100 <EvanR> with additional files you have to have
2022-12-07 05:41:07 +0100 <EvanR> to configure it
2022-12-07 05:41:19 +0100 <dsal> Sure, these are also dependencies. People are wanting packages that aren't stock.
2022-12-07 05:41:59 +0100werneta(~werneta@70-142-214-115.lightspeed.irvnca.sbcglobal.net) (Ping timeout: 256 seconds)
2022-12-07 05:42:11 +0100king_gs(~Thunderbi@2806:103e:29:94a4:81e0:429b:22ec:cf13) (Ping timeout: 264 seconds)
2022-12-07 05:42:19 +0100 <dsal> python has like, three different ways they've solved this problem so like, we're on par, I guess.
2022-12-07 05:42:21 +0100 <EvanR> yeah, if you have the dependencies, then you still can't just compile the haskell code
2022-12-07 05:42:39 +0100 <dsal> Similar with python virtualenv.
2022-12-07 05:42:51 +0100 <EvanR> yeah so python isn't "scripting" anymore xD
2022-12-07 05:42:54 +0100 <dsal> heh
2022-12-07 05:43:00 +0100 <dsal> I've got python scripts I can't run anymore. :(
2022-12-07 05:43:07 +0100 <dsal> Also, :) I don't like working in python
2022-12-07 05:44:02 +0100 <sm> albet70: custom.hs should be Custom.hs
2022-12-07 05:45:16 +0100 <albet70> ok
2022-12-07 05:45:45 +0100jpds2(~jpds@gateway/tor-sasl/jpds)
2022-12-07 05:46:14 +0100jpds1(~jpds@gateway/tor-sasl/jpds) (Ping timeout: 255 seconds)
2022-12-07 05:51:07 +0100 <albet70> if my cabal project is with 'executable' not as 'library', do I need to 'exposed-modules' for my own modules?
2022-12-07 05:53:54 +0100poljar(~poljar@93-139-83-160.adsl.net.t-com.hr)
2022-12-07 05:54:25 +0100 <sm> I don't think so...
2022-12-07 05:54:26 +0100 <sm> does it build ?
2022-12-07 05:55:16 +0100poljar1(~poljar@93-139-1-236.adsl.net.t-com.hr) (Ping timeout: 248 seconds)
2022-12-07 05:57:19 +0100waleee(~waleee@h-176-10-137-138.NA.cust.bahnhof.se) (Ping timeout: 260 seconds)
2022-12-07 06:02:45 +0100johnw(~johnw@2600:1700:cf00:db0:ccd8:6dba:13b3:7200) (Quit: ZNC - http://znc.in)
2022-12-07 06:05:25 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0) (Remote host closed the connection)
2022-12-07 06:05:43 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0)
2022-12-07 06:07:10 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0) (Remote host closed the connection)
2022-12-07 06:07:11 +0100Vajb(~Vajb@2001:999:504:3ad6:52a4:a3b5:32d8:e74d) (Read error: Connection reset by peer)
2022-12-07 06:07:40 +0100Vajb(~Vajb@hag-jnsbng11-58c3a5-27.dhcp.inet.fi)
2022-12-07 06:08:51 +0100 <chreekat> It'll build regardless,I think
2022-12-07 06:10:09 +0100jpds2(~jpds@gateway/tor-sasl/jpds) (Remote host closed the connection)
2022-12-07 06:10:31 +0100jpds2(~jpds@gateway/tor-sasl/jpds)
2022-12-07 06:12:03 +0100Lumia(~Lumia@user/Lumia)
2022-12-07 06:13:59 +0100money_(~money@user/polo)
2022-12-07 06:14:05 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Read error: Connection reset by peer)
2022-12-07 06:14:11 +0100sammelweis_(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 06:20:55 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 06:21:42 +0100Erutuon(~Erutuon@user/erutuon)
2022-12-07 06:23:12 +0100 <albet70> sm , no nedd for exposed-modules, it build
2022-12-07 06:24:34 +0100 <jackdk> Where would the modules be exposed to? You can't depend on an executable from another library, ferexample.
2022-12-07 06:26:48 +0100Vajb(~Vajb@hag-jnsbng11-58c3a5-27.dhcp.inet.fi) (Read error: Connection reset by peer)
2022-12-07 06:27:26 +0100Vajb(~Vajb@2001:999:504:3ad6:52a4:a3b5:32d8:e74d)
2022-12-07 06:30:55 +0100Lumia(~Lumia@user/Lumia) (Ping timeout: 260 seconds)
2022-12-07 06:33:33 +0100 <albet70> it should be listed in 'other-modules'
2022-12-07 06:44:33 +0100 <dibblego> @src words
2022-12-07 06:44:33 +0100 <lambdabot> words s = case dropWhile isSpace s of
2022-12-07 06:44:33 +0100 <lambdabot> "" -> []
2022-12-07 06:44:33 +0100 <lambdabot> s' -> w : words s'' where (w, s'') = break isSpace s'
2022-12-07 06:52:26 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 256 seconds)
2022-12-07 06:52:29 +0100np(~nerdypepp@user/nerdypepper) (Quit: bye)
2022-12-07 06:52:31 +0100werneta(~werneta@70-142-214-115.lightspeed.irvnca.sbcglobal.net)
2022-12-07 06:53:47 +0100nerdypepper(~nerdypepp@user/nerdypepper)
2022-12-07 06:53:49 +0100tabaqui(~root@88.231.62.215) (Quit: WeeChat 3.7.1)
2022-12-07 06:54:27 +0100tabaqui(~root@88.231.62.215)
2022-12-07 07:01:11 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Remote host closed the connection)
2022-12-07 07:02:26 +0100freeside(~mengwong@103.252.202.193)
2022-12-07 07:04:03 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 07:04:04 +0100califax(~califax@user/califx) (Write error: Connection reset by peer)
2022-12-07 07:04:04 +0100jpds2(~jpds@gateway/tor-sasl/jpds) (Write error: Connection reset by peer)
2022-12-07 07:04:04 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex) (Read error: Connection reset by peer)
2022-12-07 07:05:09 +0100califax(~califax@user/califx)
2022-12-07 07:05:23 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0)
2022-12-07 07:05:25 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 07:06:25 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex)
2022-12-07 07:07:05 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 07:07:19 +0100instantaphex(~jb@c-73-171-252-84.hsd1.fl.comcast.net) (Ping timeout: 260 seconds)
2022-12-07 07:07:26 +0100jpds2(~jpds@gateway/tor-sasl/jpds)
2022-12-07 07:08:52 +0100freeside(~mengwong@103.252.202.193) (Ping timeout: 248 seconds)
2022-12-07 07:12:59 +0100freeside(~mengwong@103.252.202.193)
2022-12-07 07:17:22 +0100takuan(~takuan@178-116-218-225.access.telenet.be)
2022-12-07 07:17:35 +0100freeside(~mengwong@103.252.202.193) (Ping timeout: 264 seconds)
2022-12-07 07:28:00 +0100 <iqubic> I'm looking to write a megaparsec parser of the type "Parser String" which parses any string at all until a white space char is hit, and I don't want to consume the whitespace.
2022-12-07 07:30:53 +0100trev(~trev@user/trev)
2022-12-07 07:32:54 +0100 <glguy> iqubic: look up : satisfy
2022-12-07 07:38:11 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 07:41:23 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:3422:7256:484b:e1c0) (Ping timeout: 260 seconds)
2022-12-07 07:42:53 +0100kenran(~user@user/kenran)
2022-12-07 07:43:39 +0100lisbeths(uid135845@id-135845.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2022-12-07 07:44:34 +0100kenran(~user@user/kenran) (Remote host closed the connection)
2022-12-07 07:45:56 +0100jpds2(~jpds@gateway/tor-sasl/jpds) (Ping timeout: 255 seconds)
2022-12-07 07:48:21 +0100jpds2(~jpds@gateway/tor-sasl/jpds)
2022-12-07 07:48:25 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex) (Remote host closed the connection)
2022-12-07 07:49:39 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex)
2022-12-07 07:50:48 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 07:51:23 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 07:59:43 +0100Unicorn_Princess(~Unicorn_P@user/Unicorn-Princess/x-3540542)
2022-12-07 08:03:16 +0100Erutuon(~Erutuon@user/erutuon) (Ping timeout: 256 seconds)
2022-12-07 08:04:50 +0100incertia(~incertia@209.122.71.127) (Ping timeout: 260 seconds)
2022-12-07 08:11:21 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 08:12:51 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 08:15:40 +0100bgs(~bgs@212-85-160-171.dynamic.telemach.net) (Remote host closed the connection)
2022-12-07 08:18:04 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 08:20:40 +0100akegalj(~akegalj@78-3-45-50.adsl.net.t-com.hr)
2022-12-07 08:22:59 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 265 seconds)
2022-12-07 08:24:05 +0100L29Ah(~L29Ah@wikipedia/L29Ah) (Ping timeout: 260 seconds)
2022-12-07 08:26:12 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:1b9f:5d8:d1e3:a25a)
2022-12-07 08:31:50 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex) (Ping timeout: 255 seconds)
2022-12-07 08:33:49 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex)
2022-12-07 08:34:11 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:95ed:d852:31e3:4446)
2022-12-07 08:34:18 +0100gimmeanickel(~gimmeanic@2405:9800:b640:c2eb:95ed:d852:31e3:4446) (Remote host closed the connection)
2022-12-07 08:35:30 +0100jinsun(~jinsun@user/jinsun) ()
2022-12-07 08:41:17 +0100bontaq(~user@ool-45779fe5.dyn.optonline.net) (Ping timeout: 252 seconds)
2022-12-07 08:47:03 +0100razetime(~quassel@49.207.203.213) (Read error: Connection reset by peer)
2022-12-07 08:47:16 +0100razetime(~quassel@49.207.203.213)
2022-12-07 08:48:36 +0100michalz(~michalz@185.246.204.75)
2022-12-07 08:50:40 +0100lisbeths(uid135845@id-135845.lymington.irccloud.com)
2022-12-07 08:52:43 +0100incertia(~incertia@209.122.71.127)
2022-12-07 08:53:14 +0100Kaiepi(~Kaiepi@108.175.84.104)
2022-12-07 09:03:37 +0100zant(~zant@62.214.20.26)
2022-12-07 09:03:50 +0100jakalx(~jakalx@base.jakalx.net) ()
2022-12-07 09:06:24 +0100freeside(~mengwong@103.252.202.193)
2022-12-07 09:07:21 +0100freeside_(~mengwong@103.252.202.193)
2022-12-07 09:11:40 +0100mncheck(~mncheck@193.224.205.254)
2022-12-07 09:14:10 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6) (Remote host closed the connection)
2022-12-07 09:14:29 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6)
2022-12-07 09:17:38 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 09:18:31 +0100coot(~coot@213.134.171.3)
2022-12-07 09:19:52 +0100bjourne2(~bjorn@94.191.136.236.mobile.tre.se)
2022-12-07 09:21:10 +0100bjourne2(~bjorn@94.191.136.236.mobile.tre.se) (Client Quit)
2022-12-07 09:22:43 +0100gmg(~user@user/gehmehgeh)
2022-12-07 09:24:36 +0100kazaf(~kazaf@37.112.34.29)
2022-12-07 09:25:25 +0100zeenk(~zeenk@2a02:2f04:a30d:4300::7fe)
2022-12-07 09:26:02 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:111a:339b:4372:c307) (Remote host closed the connection)
2022-12-07 09:28:58 +0100fserucas__(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr)
2022-12-07 09:32:52 +0100Scraeling(~Scraeling@user/scraeling)
2022-12-07 09:36:07 +0100sammelweis_(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
2022-12-07 09:36:14 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 09:36:41 +0100avicenzi(~avicenzi@2a00:ca8:a1f:b004::c32)
2022-12-07 09:36:55 +0100MajorBiscuit(~MajorBisc@2a02-a461-129d-1-193d-75d8-745d-e91e.fixed6.kpn.net)
2022-12-07 09:36:57 +0100phma(phma@2001:5b0:2144:44d8:212c:2869:b063:882b) (Read error: Connection reset by peer)
2022-12-07 09:37:38 +0100phma(~phma@host-67-44-208-200.hnremote.net)
2022-12-07 09:42:15 +0100MajorBiscuit(~MajorBisc@2a02-a461-129d-1-193d-75d8-745d-e91e.fixed6.kpn.net) (Ping timeout: 260 seconds)
2022-12-07 09:43:11 +0100MajorBiscuit(~MajorBisc@c-001-003-046.client.tudelft.eduvpn.nl)
2022-12-07 09:45:49 +0100Sgeo(~Sgeo@user/sgeo) (Read error: Connection reset by peer)
2022-12-07 09:48:48 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Read error: Connection reset by peer)
2022-12-07 09:49:54 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 09:53:16 +0100machinedgod(~machinedg@d198-53-218-113.abhsia.telus.net)
2022-12-07 09:53:40 +0100use-value1(~Thunderbi@2a00:23c6:8a03:2f01:556e:28e8:6695:53e8)
2022-12-07 09:55:47 +0100use-value(~Thunderbi@2a00:23c6:8a03:2f01:69a2:269b:4e3d:1c6) (Ping timeout: 265 seconds)
2022-12-07 09:55:47 +0100use-value1use-value
2022-12-07 09:56:30 +0100acidjnk_new(~acidjnk@p200300d6e7137a66c53ce5ddc06be1e3.dip0.t-ipconnect.de)
2022-12-07 09:56:58 +0100fserucas__(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr) (Quit: Leaving)
2022-12-07 09:57:09 +0100fserucas(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr)
2022-12-07 09:59:13 +0100functional(~functiona@119.8.243.19)
2022-12-07 10:09:08 +0100ft(~ft@p508dbd59.dip0.t-ipconnect.de) (Quit: leaving)
2022-12-07 10:14:14 +0100functional(~functiona@119.8.243.19) (Quit: Client closed)
2022-12-07 10:14:19 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 10:16:09 +0100kimiamania(~65804703@user/kimiamania)
2022-12-07 10:23:54 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection)
2022-12-07 10:25:40 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 10:26:31 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43)
2022-12-07 10:28:23 +0100gmg(~user@user/gehmehgeh) (Ping timeout: 255 seconds)
2022-12-07 10:28:23 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Ping timeout: 255 seconds)
2022-12-07 10:28:36 +0100jakalx(~jakalx@base.jakalx.net)
2022-12-07 10:29:41 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 10:30:17 +0100gmg(~user@user/gehmehgeh)
2022-12-07 10:30:53 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43) (Ping timeout: 246 seconds)
2022-12-07 10:31:57 +0100alexiscott(~user@4.red-83-36-45.dynamicip.rima-tde.net)
2022-12-07 10:34:14 +0100CiaoSen(~Jura@p200300c95747e0002a3a4dfffe84dbd5.dip0.t-ipconnect.de)
2022-12-07 10:42:36 +0100zeenk(~zeenk@2a02:2f04:a30d:4300::7fe) (Quit: Konversation terminated!)
2022-12-07 10:45:25 +0100gurkenglas(~gurkengla@p548ac72e.dip0.t-ipconnect.de)
2022-12-07 10:46:34 +0100szkl(uid110435@id-110435.uxbridge.irccloud.com)
2022-12-07 10:47:43 +0100ubert1(~Thunderbi@2a02:8109:abc0:6434:3dae:2edc:412:e26e)
2022-12-07 10:48:04 +0100chele(~chele@user/chele)
2022-12-07 10:51:47 +0100gmg(~user@user/gehmehgeh) (Ping timeout: 255 seconds)
2022-12-07 10:52:45 +0100nschoe(~q@141.101.51.197)
2022-12-07 10:53:48 +0100kalj(~kalj@78-71-20-170-no193.tbcn.telia.com)
2022-12-07 10:53:54 +0100zant(~zant@62.214.20.26) (Ping timeout: 252 seconds)
2022-12-07 10:57:37 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net)
2022-12-07 10:59:20 +0100c_wraith(~c_wraith@adjoint.us) (Ping timeout: 255 seconds)
2022-12-07 10:59:35 +0100mtjm_(~mutantmel@2604:a880:2:d0::208b:d001)
2022-12-07 10:59:46 +0100Patternmaster(~georg@user/Patternmaster) (Ping timeout: 252 seconds)
2022-12-07 11:00:15 +0100mtjm(~mutantmel@2604:a880:2:d0::208b:d001) (Ping timeout: 255 seconds)
2022-12-07 11:00:31 +0100 <kalj> What is the haskell way to take a datastructure and transform it in some minor way? I have a [(String,[String])], (string keys and list-of-strings values) and I want to do append something to the inner list where the key equals something, say "banana". I could do it by mapping something like \(k,v) -> if k=="banana" then (k,v++["newelem"]) else
2022-12-07 11:00:31 +0100 <kalj> (k,v), but if the data structure gets more complex, you get a lot of map's and lambda's.
2022-12-07 11:00:34 +0100Patternmaster(~georg@user/Patternmaster)
2022-12-07 11:01:22 +0100 <dminuoso> kalj: Difficult to answer in a general manner.
2022-12-07 11:01:32 +0100c_wraith(~c_wraith@adjoint.us)
2022-12-07 11:02:23 +0100 <dminuoso> To describe nested access and mutation, `lens` or `optics` are common solutions.
2022-12-07 11:02:54 +0100 <kalj> dminuoso Thanks, I will have a look.
2022-12-07 11:03:02 +0100 <dminuoso> So the access you described would be formulated as:
2022-12-07 11:04:27 +0100mtjm_mtjm
2022-12-07 11:05:18 +0100 <dminuoso> kalj: data & at "banana" %~ (++ ["newelem"])
2022-12-07 11:05:40 +0100 <dminuoso> Which would work for `optics` at least.
2022-12-07 11:06:05 +0100 <dminuoso> If you're relatively new, I would recommend you look into `optics` first, as it is better structured and documented, and has much better diagnostic.
2022-12-07 11:06:29 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 11:07:01 +0100 <jackdk> Does optics have an `At` instance for alists?
2022-12-07 11:07:22 +0100 <iqubic> What ar alists?
2022-12-07 11:07:25 +0100tzh(~tzh@c-24-21-73-154.hsd1.wa.comcast.net) (Quit: zzz)
2022-12-07 11:07:27 +0100xff0x(~xff0x@125x103x176x34.ap125.ftth.ucom.ne.jp) (Ping timeout: 255 seconds)
2022-12-07 11:08:21 +0100 <dminuoso> jackdk: Ah good point, this should be written as `data & traversed & at "banana" %~ (++ ["newelem"])
2022-12-07 11:08:38 +0100 <dminuoso> Gah. typo
2022-12-07 11:08:44 +0100 <dminuoso> data & traversed % at "banana" %~ (++ ["newelem"])
2022-12-07 11:09:19 +0100 <iqubic> What are alists in this context?
2022-12-07 11:09:20 +0100 <iqubic> What are alists in this context?
2022-12-07 11:09:28 +0100 <dminuoso> iqubic: [(k, v)]
2022-12-07 11:09:49 +0100 <dminuoso> Come to think of it, maybe at wouldnt actually work
2022-12-07 11:10:07 +0100 <dminuoso> So you need to use `ix`
2022-12-07 11:10:44 +0100 <dminuoso> and that wouldnt work either, a0 ~ a1 => Ixed (a0, a1)
2022-12-07 11:10:46 +0100 <dminuoso> Sigh mmm
2022-12-07 11:11:01 +0100 <dminuoso> Then something like
2022-12-07 11:11:09 +0100 <jackdk> iqubic: https://en.wikipedia.org/wiki/Association_list
2022-12-07 11:11:58 +0100acidjnk_new(~acidjnk@p200300d6e7137a66c53ce5ddc06be1e3.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
2022-12-07 11:12:41 +0100 <iqubic> jackdk: Neither Optics nor Lens provide a default for that type.
2022-12-07 11:12:44 +0100 <dminuoso> Is there a kind of `eq :: s -> Getter s s`?
2022-12-07 11:13:23 +0100 <dminuoso> Or no Getter is not enough. Should be Fold, perhaps
2022-12-07 11:13:34 +0100 <iqubic> What are you trying to do here?
2022-12-07 11:13:46 +0100 <iqubic> Fold is like Getter, but multiple targets.
2022-12-07 11:14:19 +0100Lord_of_Life_(~Lord@user/lord-of-life/x-2819915)
2022-12-07 11:14:36 +0100 <dminuoso> In optics lingo I would be looking for an AffineFold rather
2022-12-07 11:15:00 +0100Lord_of_Life(~Lord@user/lord-of-life/x-2819915) (Ping timeout: 260 seconds)
2022-12-07 11:15:08 +0100 <dminuoso> The relevant difference with a getter is that the fold could fail
2022-12-07 11:15:17 +0100 <iqubic> Yeah... I see
2022-12-07 11:15:20 +0100 <kalj> Amazing.
2022-12-07 11:15:32 +0100 <dminuoso> kalj: Im conjuring up a proper solution for what you asked for, the above is wrong.
2022-12-07 11:15:41 +0100 <jackdk> we've gone into the weeds kalj. I'll have something sensible for you in a sec
2022-12-07 11:15:49 +0100 <jackdk> and then I'll go back into the weeds too ^^
2022-12-07 11:16:07 +0100 <dminuoso> I guess I can use `filtered (== "foo")
2022-12-07 11:16:37 +0100 <iqubic> What was Kalj's initial question?
2022-12-07 11:16:42 +0100 <xerox> glguy: thanks for the idea of skipping the dirs in the listings and working with tails path it came out pretty neat that way
2022-12-07 11:17:03 +0100Lord_of_Life_Lord_of_Life
2022-12-07 11:17:14 +0100acidjnk_new(~acidjnk@p200300d6e7137a66c53ce5ddc06be1e3.dip0.t-ipconnect.de)
2022-12-07 11:17:33 +0100 <jackdk> "I have a [(String,[String])], (string keys and list-of-strings values) and I want to do append something to the inner list where the key equals something, say "banana". I could do it by mapping something like \(k,v) -> if k=="banana" then (k,v++["newelem"]) else (k,v), but if the data structure gets more complex, you get a lot of map's and lambda's."
2022-12-07 11:18:12 +0100 <kalj> great. I am kind of interested in the general question, so the original question is maybe not super important. Basically, if you have non-trivial data structure, how do you do "updates" to it. Maybe I still think in a too imperative way, this is something that I can't seem to work my way around
2022-12-07 11:18:16 +0100 <dminuoso> let eqing a = unsafeFiltered (== a) in data & traversed % unsafeFilteredBy (_1 % eqing "banana") % _2 %~ (++ ["newelem"])
2022-12-07 11:18:20 +0100 <dminuoso> This would work with optics.
2022-12-07 11:18:25 +0100 <xerox> oh wrong channel, meant for aoc-spoilers
2022-12-07 11:18:51 +0100 <dminuoso> kalj: Okay yes, for that general question `optics` or `lens` it that answer.
2022-12-07 11:19:03 +0100 <dminuoso> Especially if the data can get quite nested.
2022-12-07 11:19:13 +0100 <dminuoso> If its relatively shallow it may not be that useful
2022-12-07 11:19:21 +0100 <kalj> @dmin Cool
2022-12-07 11:19:21 +0100 <lambdabot> Not enough privileges
2022-12-07 11:19:34 +0100 <kalj> :P
2022-12-07 11:20:30 +0100 <jackdk> kalj: Here is a non-lensy way of attacking your problem https://www.irccloud.com/pastebin/IeHn3hi9/NotLensy.hs
2022-12-07 11:20:43 +0100 <dminuoso> The above can be written in lens equivalently, you just write `filteredBy` and `filtered` instead (funnily, they are actually much unsafer, despite lacking the word `unsafe`)
2022-12-07 11:21:33 +0100 <jackdk> kalj: basically, the `alistModify` function takes a "key" (here, your `String`) and a function that describes what to do with the value, if it exists, and then updates the list.
2022-12-07 11:21:38 +0100 <dminuoso> Of course it should be said, that the deeper the nested access goes, the less fun writing it out will be.
2022-12-07 11:22:36 +0100 <dminuoso> If the data is as shallow as you made it out, I would write it like jackdk (unless I already had optics around). With each additional data level, I would get more and more likely to use `optics`
2022-12-07 11:22:50 +0100 <jackdk> kalj: the trick is in the order of arguments - by putting the data structure as the last argument, you can partially apply the function and get a function like `(Maybe v -> Maybe v) -> ([(k, v)] -> [(k, v)])`, which plays nicely with `(.)` (function composition)
2022-12-07 11:23:04 +0100 <jackdk> Lemme check my misc repo, maybe I have a good example
2022-12-07 11:23:38 +0100 <dminuoso> Another thing you can also do, is to use a `Map String [String]` rather than `[(String, [String])]` (assuming keys are unique), because `Map` already comes with `alter` or `alterF`
2022-12-07 11:24:34 +0100 <dminuoso> take note that jackdk's function is of type:
2022-12-07 11:24:37 +0100 <dminuoso> alter :: (Maybe a -> Maybe a) -> Key -> IntMap a -> IntMap a
2022-12-07 11:24:42 +0100 <jackdk> kalj: https://git.sr.ht/~jack/misc/tree/master/item/codeworld-raycaster/src/State.hs#L39-43 doesn't do _nested_ updates, but is another example of the pattern
2022-12-07 11:24:43 +0100 <dminuoso> 'alter :: (Maybe a -> Maybe a) -> Key -> IntMap a -> IntMap a
2022-12-07 11:24:49 +0100 <dminuoso> alistModify :: Eq k => k -> (Maybe v -> Maybe v) -> [(k, v)] -> [(k, v)]
2022-12-07 11:25:01 +0100 <dminuoso> alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a
2022-12-07 11:25:06 +0100 <kalj> I am amazed!
2022-12-07 11:25:08 +0100 <dminuoso> So this directly mimics `alter` from Map. :)
2022-12-07 11:25:16 +0100 <kalj> Cool stuff, I definitely have some reading up to do
2022-12-07 11:25:31 +0100 <kalj> Yeah, I should definitely use a Map in this case
2022-12-07 11:26:25 +0100 <jackdk> Yeah, this all looked way harder because unlike lispers, we don't use association lists very much
2022-12-07 11:27:24 +0100 <dminuoso> `optics` and `lens` provide a very generalized framework for expression pretty much any type of access patterns (i.e. "go over each element in the list, left side of a tuple, inside the map key at "foo", add 1 over element in the (Int, Int, Int) tuple)), or you want to extract information, or just set it, etc..
2022-12-07 11:27:52 +0100 <dminuoso> But it's quite a large dependency to include for just a singular use case.
2022-12-07 11:28:47 +0100 <jackdk> I would strongly recommend learning lens **eventually**, because it's so useful, but first learn "normal" haskell
2022-12-07 11:29:16 +0100 <kalj> Anyways, another nooby question: how do you typically troubleshoot haskell code? I am noticing that stuff end up giving the wrong result, but I can't just "printf debug" like I'm used to. How would one go about trying to inspect values in the middle of a computation_
2022-12-07 11:29:36 +0100 <dminuoso> jackdk: Im wondering whether we should perhaps have a kind of `alist :: IxTraversal k (k, a) (k, b) a b` utility in lens and optics.
2022-12-07 11:29:54 +0100 <dminuoso> At first glance that seems easy to write and useful
2022-12-07 11:30:40 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua) (Ping timeout: 256 seconds)
2022-12-07 11:31:02 +0100 <dminuoso> Or mmm, no actually that would have to be an IxFold to work out
2022-12-07 11:31:02 +0100 <jackdk> dminuoso: I almost never use alists, so I'm not super fussed either way. I don't think you can change type though, unless you change it in every member at once?
2022-12-07 11:31:18 +0100 <dminuoso> Sure, but that's how it works anyway?
2022-12-07 11:31:50 +0100 <jackdk> kalj: You can fake "printf debugging" using the functions in `Debug.Trace` - I find `traceShowId` most useful - "print the thing if it can be shown, then return it"
2022-12-07 11:31:56 +0100 <dminuoso> Call it `aelem :: IxFold k (k, a) (k, b) a b` -- if you compose this onto a `traversed % aelem` you can simply swap out the value side of an alist.
2022-12-07 11:32:20 +0100 <dminuoso> Or gah, this wont work either. It needs IxTraversal really.
2022-12-07 11:32:35 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:1b9f:5d8:d1e3:a25a) (Ping timeout: 264 seconds)
2022-12-07 11:33:03 +0100 <jackdk> dminuoso: if it's a fold then you'll only get a fold when you compose with a traversal but - I think you want `assoc :: Eq k => k -> Lens' [(k, a)] (Maybe a)`
2022-12-07 11:33:31 +0100 <jackdk> kalj: but more often, I test smaller and smaller parts of my code in a repl, until I've isolated the thing that is misbehaving
2022-12-07 11:33:34 +0100 <dminuoso> jackdk: I think an IxTraversal is more useful.
2022-12-07 11:34:29 +0100 <jackdk> kalj: because haskell is pure, you can evaluate things by hand as well - that's often a good way to see what's going wrong
2022-12-07 11:34:49 +0100 <dminuoso> jackdk: You can use `trace` (and all similar trace* functions) to debug evaluation.
2022-12-07 11:34:57 +0100 <dminuoso> https://hackage.haskell.org/package/base-4.17.0.0/docs/Debug-Trace.html#v:trace
2022-12-07 11:34:59 +0100 <jackdk> dminuoso: I just said that
2022-12-07 11:35:21 +0100 <jackdk> thanks for the haddock link though - should've posted that too
2022-12-07 11:35:22 +0100 <dminuoso> jackdk: Oh, there was a weird line break in weechat, mentally I skipped what was above.
2022-12-07 11:35:45 +0100 <dminuoso> Not sure why weechat does occacsionally print `- - - - - - ...`
2022-12-07 11:36:35 +0100 <dminuoso> jackdk: Also, even your assoc should be an (Affine) traversal, rather than a `Lens'` onto a Maybe.
2022-12-07 11:36:56 +0100 <dminuoso> Im not entirely sure why `at` uses Lens onto Maybe as well
2022-12-07 11:37:19 +0100 <jackdk> dminuoso: because unlike `ix`, `at` allows you to create and delete entries. I wanted the same for `assoc`.
2022-12-07 11:37:24 +0100 <mauke> xerox: what is aoc-spoilers?
2022-12-07 11:37:25 +0100 <dminuoso> Ohhh
2022-12-07 11:38:20 +0100 <dminuoso> Yeah that makes sense. `assoc :: Eq k => k -> IxLens k [(k, a)] (Maybe a)` it is (took the liberty of adding the Ix part to it)
2022-12-07 11:39:12 +0100 <kalj> Thanks, Debug.Trace helps!
2022-12-07 11:39:15 +0100 <mauke> dminuoso: did you switch tabs in between? (i.e. is it a "last position before switch" marker?)
2022-12-07 11:39:36 +0100 <dminuoso> mauke: not sure
2022-12-07 11:40:17 +0100 <dminuoso> (though perhaps the Ix part is completely redundant, since you already have access to the key...)
2022-12-07 11:41:02 +0100 <dminuoso> jackdk: Could Wither be a thing in lens/optics world?
2022-12-07 11:41:22 +0100 <mauke> (I once implemented that feature as a ChatZilla add-on)
2022-12-07 11:41:50 +0100 <dminuoso> type WitherLike f s t a b = (a -> f (Maybe b)) -> s -> f t
2022-12-07 11:41:52 +0100 <dminuoso> type Wither s t a b = forall f. Applicative f => WitherLike f s t a b
2022-12-07 11:41:54 +0100 <dminuoso> Mmmm
2022-12-07 11:42:21 +0100 <dminuoso> That's cute :)
2022-12-07 11:42:24 +0100 <jackdk> dminuoso: https://old.reddit.com/r/haskell/comments/jlr1g4/blog_composable_filtering_optics_using_witherable/ in my browser history, but I don't have an opinion on it
2022-12-07 11:51:23 +0100mmhat(~mmh@p200300f1c73b5136ee086bfffe095315.dip0.t-ipconnect.de)
2022-12-07 11:51:49 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt)
2022-12-07 11:53:12 +0100 <iqubic> Does that work with Lens?
2022-12-07 11:56:36 +0100mmhat(~mmh@p200300f1c73b5136ee086bfffe095315.dip0.t-ipconnect.de) (Quit: WeeChat 3.7.1)
2022-12-07 11:56:47 +0100econo(uid147250@user/econo) (Quit: Connection closed for inactivity)
2022-12-07 12:00:23 +0100lisbeths(uid135845@id-135845.lymington.irccloud.com) (Quit: Connection closed for inactivity)
2022-12-07 12:02:13 +0100fserucas(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr) (Ping timeout: 256 seconds)
2022-12-07 12:03:02 +0100bjourne(~bjourne@2001:6b0:1:1140:42bf:ff4:f8fa:50e5) (Quit: Konversation terminated!)
2022-12-07 12:04:22 +0100 <xerox> mauke: #adventofcode-spoilers
2022-12-07 12:04:40 +0100jmdaemon(~jmdaemon@user/jmdaemon) (Ping timeout: 256 seconds)
2022-12-07 12:05:44 +0100xff0x(~xff0x@ai071162.d.east.v6connect.net)
2022-12-07 12:07:40 +0100 <jackdk> iqubic: It's got the same vague shape, so maybe?
2022-12-07 12:08:23 +0100 <iqubic> Is Witherable ever gonna get added to the core Lens library?
2022-12-07 12:12:24 +0100gurkenglas(~gurkengla@p548ac72e.dip0.t-ipconnect.de) (Ping timeout: 260 seconds)
2022-12-07 12:15:02 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex) (Ping timeout: 255 seconds)
2022-12-07 12:15:50 +0100zant(~zant@2a00:20:6017:5cfb:1db8:b3f9:e08:f0dd)
2022-12-07 12:16:05 +0100Chai-T-Rex(~ChaiTRex@user/chaitrex)
2022-12-07 12:16:23 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Ping timeout: 255 seconds)
2022-12-07 12:18:52 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex)
2022-12-07 12:20:18 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
2022-12-07 12:21:36 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 12:23:35 +0100ec_(~ec@gateway/tor-sasl/ec) (Ping timeout: 255 seconds)
2022-12-07 12:25:59 +0100zant1(~zant@2a00:20:6017:5cfb:7889:b51c:c40a:b6bb)
2022-12-07 12:26:04 +0100ec_(~ec@gateway/tor-sasl/ec)
2022-12-07 12:27:05 +0100zant(~zant@2a00:20:6017:5cfb:1db8:b3f9:e08:f0dd) (Ping timeout: 255 seconds)
2022-12-07 12:31:10 +0100razetime(~quassel@49.207.203.213) (Ping timeout: 268 seconds)
2022-12-07 12:31:29 +0100razetime(~quassel@49.207.203.213)
2022-12-07 12:34:03 +0100amano[m](~amanocute@2001:470:69fc:105::2:d3f4)
2022-12-07 12:34:53 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:ebf5:c68c:db4f:4f95)
2022-12-07 12:42:36 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:897b:5682:aa16:df9e)
2022-12-07 12:42:45 +0100 <o1lo01ol1o> I have an hspec test in a suite that fails when run in cabal test but which passes in ghci. Are there any resources for what may be going on?
2022-12-07 12:43:10 +0100DigitalKiwi(~kiwi@2604:a880:400:d0::1ca0:e001) (Quit: quite.)
2022-12-07 12:43:55 +0100DigitalKiwi(~kiwi@137.184.156.191)
2022-12-07 12:44:23 +0100zant1(~zant@2a00:20:6017:5cfb:7889:b51c:c40a:b6bb) (Ping timeout: 252 seconds)
2022-12-07 12:44:54 +0100kazaf(~kazaf@37.112.34.29) (Ping timeout: 256 seconds)
2022-12-07 12:49:11 +0100haritz(~hrtz@user/haritz) (Quit: ZNC 1.8.2+deb2 - https://znc.in)
2022-12-07 12:54:41 +0100dextaa2(~DV@user/dextaa)
2022-12-07 12:57:04 +0100dextaa(~DV@user/dextaa) (Ping timeout: 268 seconds)
2022-12-07 12:57:05 +0100dextaa2dextaa
2022-12-07 13:00:28 +0100jakalx(~jakalx@base.jakalx.net) ()
2022-12-07 13:00:37 +0100 <albet70> is that any run-time exceptions are IO Exceptions?
2022-12-07 13:01:30 +0100 <albet70> is 1/0 an exception?
2022-12-07 13:02:38 +0100 <mauke> > 1/0
2022-12-07 13:02:39 +0100 <[exa]> AFAIK there's no other reasonable way to "receive" an exception than IO (maybe ST)
2022-12-07 13:02:39 +0100 <lambdabot> Infinity
2022-12-07 13:03:03 +0100 <dminuoso> [exa]: ST cant have exceptions (and I finally understood why too!)
2022-12-07 13:03:09 +0100 <xerox> > 1/(1/0)
2022-12-07 13:03:10 +0100 <lambdabot> 0.0
2022-12-07 13:03:16 +0100 <[exa]> dminuoso: ah okay, good. :D
2022-12-07 13:03:27 +0100CiaoSen(~Jura@p200300c95747e0002a3a4dfffe84dbd5.dip0.t-ipconnect.de) (Ping timeout: 252 seconds)
2022-12-07 13:03:51 +0100 <merijn> Dividing by 0 isn't an exception for Doubles
2022-12-07 13:04:08 +0100 <merijn> It's just positive/negative infinity
2022-12-07 13:04:30 +0100 <[exa]> > div 1 0
2022-12-07 13:04:31 +0100 <dminuoso> albet70: And no, IO exceptions are separate from pure exceptions.
2022-12-07 13:04:31 +0100 <lambdabot> *Exception: divide by zero
2022-12-07 13:04:47 +0100__monty__(~toonn@user/toonn)
2022-12-07 13:05:02 +0100 <dminuoso> albet70: THere's even semantic differences between them, see https://www.microsoft.com/en-us/research/publication/a-semantics-for-imprecise-exceptions/
2022-12-07 13:05:06 +0100 <[exa]> dminuoso: btw what's the actual reason? (/me curious)
2022-12-07 13:05:34 +0100 <mniip> [exa], you can catch them inside runST and now suddenly you're catching in pure code
2022-12-07 13:05:48 +0100 <albet70> my real question is this https://hackage.haskell.org/package/scotty-0.12.1/docs/src/Web.Scotty.html#rescue
2022-12-07 13:05:57 +0100 <[exa]> mniip: ah yes that makes sense
2022-12-07 13:06:05 +0100 <albet70> I wonder how this 'rescue' handle exceptions
2022-12-07 13:06:41 +0100jakalx(~jakalx@base.jakalx.net)
2022-12-07 13:06:52 +0100 <mniip> albet70, probably using IO's throw and catch as seen here https://hackage.haskell.org/package/base-4.17.0.0/docs/GHC-IO.html#v:catch
2022-12-07 13:07:02 +0100 <dminuoso> albet70: It's just a pretty wrapper around https://hackage.haskell.org/package/mtl-2.3.1/docs/Control-Monad-Error-Class.html#v:catchError
2022-12-07 13:07:04 +0100zant1(~zant@62.96.232.178)
2022-12-07 13:07:18 +0100 <dminuoso> Which ends up calling `catch` like mniip pointed out
2022-12-07 13:07:36 +0100 <[exa]> mniip: thanks!
2022-12-07 13:07:56 +0100 <mniip> and IO's throw and catch are very thin wrappers around GHC RTS primitives (magic)
2022-12-07 13:10:11 +0100fserucas(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr)
2022-12-07 13:13:53 +0100 <albet70> there's a ContT r m a in that 'catch' and 'catchError'
2022-12-07 13:15:59 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
2022-12-07 13:16:09 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 13:17:33 +0100 <dminuoso> mniip: that at least makes is technically impossible as raiseIO# requires a monomorphic RealWorld parameterized state token
2022-12-07 13:19:11 +0100 <mniip> dminuoso, there's some puity/referential transparency/... reason that I can't quite remember now
2022-12-07 13:21:44 +0100048AAH6AD(~Thunderbi@179.214.113.107) (Ping timeout: 256 seconds)
2022-12-07 13:22:14 +0100 <dminuoso> mniip: raiseIO# throws precise exceptions, raise# throws imprecise exceptions. If you were allowed to throwIO# in ST, they could leak outside.
2022-12-07 13:22:23 +0100 <dminuoso> And that would violate some optimizations and analysis
2022-12-07 13:22:32 +0100bgs(~bgs@212-85-160-171.dynamic.telemach.net)
2022-12-07 13:24:25 +0100 <dminuoso> Though Im not entirely sure about runRW# in that respect, because unsafePerformIO would have the same problems mmm
2022-12-07 13:24:36 +0100euandreh(~Thunderbi@179.214.113.107)
2022-12-07 13:25:00 +0100 <albet70> dminuoso , as you said, there're two exceptions, pure exception and IO exception, is 1/0 a pure exception? that run-time exceptions are IO exception? read from file or socket is IO exception?
2022-12-07 13:25:13 +0100 <dminuoso> albet70: 1/0 actually is not an exception.
2022-12-07 13:25:19 +0100sammelweis_(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 13:25:24 +0100 <dminuoso> Or at least not depending on which type you instantiate this at
2022-12-07 13:26:18 +0100 <albet70> what about passing an String to (+), is that an exception?
2022-12-07 13:26:24 +0100 <dminuoso> A runtime exception arises from `undefined`, `error "foo"`, missing patterns, etc..
2022-12-07 13:26:34 +0100 <dminuoso> That is a type checker error.
2022-12-07 13:26:39 +0100 <dminuoso> Potentially, anyway
2022-12-07 13:26:58 +0100 <dminuoso> So `undefined`, `error "foo"`, missing patterns - these are examples of pure (and thus imprecise) exceptions
2022-12-07 13:27:17 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Ping timeout: 252 seconds)
2022-12-07 13:27:28 +0100 <dminuoso> These are catchable using `evaluate :: a -> IO a`, but it is very important to understand what `imprecise` here means before using `evaluate`.
2022-12-07 13:27:28 +0100 <albet70> (+) print print would get an 'error ...' right?
2022-12-07 13:27:37 +0100 <dminuoso> No, it would just fail to compile.
2022-12-07 13:27:41 +0100 <dminuoso> % (+) print print
2022-12-07 13:27:41 +0100 <yahb2> <interactive>:68:1: error: ; • No instance for (Num (() -> IO ())) arising from a use of ‘it’ ; (maybe you haven't applied a function to enough arguments?) ; • In the first argument...
2022-12-07 13:28:42 +0100 <dminuoso> I tend to think of pure exceptions as a kind of landmine, that when evaluation steps into will immediately abort (either the entire program, or bubble up as an IO exception at `evaluate` -- again up to the imprecise nature of pure exceptions)
2022-12-07 13:29:06 +0100 <dminuoso> In most cases it will abort.
2022-12-07 13:29:35 +0100 <albet70> could you give an example of pure exception?
2022-12-07 13:29:42 +0100 <albet70> common example
2022-12-07 13:29:42 +0100 <dminuoso> │13:26:58 dminuoso | So `undefined`, `error "foo"`, missing patterns - these are examples of pure (and thus imprecise) exceptions
2022-12-07 13:30:24 +0100 <dminuoso> % (error "thing") + 2
2022-12-07 13:30:24 +0100 <yahb2> *** Exception: thing ; CallStack (from HasCallStack): ; error, called at <interactive>:70:2 in interactive:Ghci13
2022-12-07 13:30:55 +0100 <dminuoso> % putStr "foo" >> putStr (error "no!")
2022-12-07 13:30:55 +0100 <yahb2> foo*** Exception: no! ; CallStack (from HasCallStack): ; error, called at <interactive>:72:25 in interactive:Ghci13
2022-12-07 13:30:59 +0100 <albet70> but those are raised by your intension
2022-12-07 13:31:09 +0100 <dminuoso> ^- note how the execution has already printed `foo` before the explosion?
2022-12-07 13:31:23 +0100 <albet70> intention
2022-12-07 13:31:37 +0100 <dminuoso> So there's two classes of when pure exceptions are found in Haskell code
2022-12-07 13:32:10 +0100 <dminuoso> a) positioning an `error` for seemingly impossible code. in more elaborate code, it is probably better to do some terminal error management, but `error "internal error: xyz not initialized"` is a very easy way of getting the job done.
2022-12-07 13:32:48 +0100 <dminuoso> b) writing unsafe code, like `head (x:xs) = x; head [] = error "head: empty list"`
2022-12-07 13:33:12 +0100 <dminuoso> The latter of which is often considered bad style especially in a standard library (because misusing it will usually terminate an entire program)
2022-12-07 13:33:16 +0100 <dminuoso> The worst example of this is `read`
2022-12-07 13:33:24 +0100 <dminuoso> If `read` fails, it will abort with a pure exception
2022-12-07 13:33:44 +0100 <dminuoso> % (read "100-1") :: Int
2022-12-07 13:33:44 +0100 <yahb2> *** Exception: Prelude.read: no parse
2022-12-07 13:34:35 +0100 <dminuoso> So burying a `read` inside a library is particularly awful, because it can crash your program.
2022-12-07 13:34:44 +0100 <dminuoso> Or any program that relies on that library.
2022-12-07 13:34:56 +0100 <merijn> We should just delete read from existing :p
2022-12-07 13:35:03 +0100 <dminuoso> +1
2022-12-07 13:35:17 +0100 <merijn> Replace it with readMaybe
2022-12-07 13:35:34 +0100 <dminuoso> Or better yet, proper parsing. :)
2022-12-07 13:37:36 +0100aliosablack(~chomwitt@2a02:587:7a0c:6a00:1ac0:4dff:fedb:a3f1)
2022-12-07 13:37:40 +0100 <mniip> this is a question of sane defaults and there's no right answer
2022-12-07 13:39:17 +0100 <merijn> eh
2022-12-07 13:39:30 +0100 <merijn> readMaybe is the obvious right answer for sane default
2022-12-07 13:39:33 +0100 <albet70> so there three things, 1. error before 'evaluate' like 1/0, print + print, 2. pure exception, raised by 'error' as your intention or abort like (read "a") :: Int, 3. IO exception like readFile, is this correct?
2022-12-07 13:39:37 +0100 <merijn> So, hard disagree with you there :p
2022-12-07 13:40:47 +0100 <albet70> merijn, without read, how to turn string to Int?
2022-12-07 13:41:49 +0100 <merijn> :t readMaybe
2022-12-07 13:41:50 +0100 <lambdabot> error: Variable not in scope: readMaybe
2022-12-07 13:41:53 +0100 <merijn> :O
2022-12-07 13:41:59 +0100 <merijn> :t Text.Read.readMaybe
2022-12-07 13:42:00 +0100 <lambdabot> Read a => String -> Maybe a
2022-12-07 13:42:44 +0100 <dminuoso> Or `readEither` even
2022-12-07 13:42:55 +0100 <merijn> "read" is "nice" for Advent of Code and a massive liability for literally every non-trivial code. So I'd rather make people's AoC solutions slightly more verbose :p
2022-12-07 13:43:44 +0100CiaoSen(~Jura@p200300c95747e0002a3a4dfffe84dbd5.dip0.t-ipconnect.de)
2022-12-07 13:48:30 +0100Topsi(~Topsi@217.64.164.1)
2022-12-07 13:48:49 +0100Topsi1(~Topsi@dyndsl-095-033-143-231.ewe-ip-backbone.de)
2022-12-07 13:49:11 +0100 <albet70> merijn, how about remove Maybe since Either can do the exactly same thing
2022-12-07 13:49:28 +0100 <merijn> readEither already exists too
2022-12-07 13:49:52 +0100 <albet70> :t maybe
2022-12-07 13:49:53 +0100 <lambdabot> b -> (a -> b) -> Maybe a -> b
2022-12-07 13:50:58 +0100akegalj(~akegalj@78-3-45-50.adsl.net.t-com.hr) (Quit: leaving)
2022-12-07 13:52:11 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 13:53:37 +0100bontaq(~user@ool-45779fe5.dyn.optonline.net)
2022-12-07 13:57:41 +0100johnw(~johnw@2600:1700:cf00:db0:1da8:bc45:1742:a938)
2022-12-07 14:01:00 +0100 <albet70> when b~IO b, maybe can turn a Maybe a to IO b, this is amazing I think
2022-12-07 14:04:52 +0100sammelweis_(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
2022-12-07 14:05:08 +0100bitdex(~bitdex@gateway/tor-sasl/bitdex) (Quit: = "")
2022-12-07 14:05:11 +0100Scraeling(~Scraeling@user/scraeling) (Remote host closed the connection)
2022-12-07 14:05:58 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 14:06:23 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:897b:5682:aa16:df9e) (Ping timeout: 260 seconds)
2022-12-07 14:08:09 +0100 <albet70> IIRC there is module, I forget the name, replace Either with Exception?
2022-12-07 14:08:59 +0100 <merijn> Sounds like a great way to get lynched by colleagues
2022-12-07 14:11:52 +0100 <freeside_> halp. i can haz quadratic runtime due to a memory leak. i have spent two days on AOC 2019 day 16. It really is as hard as people say it is :-(
2022-12-07 14:12:12 +0100 <freeside_> https://github.com/mengwong/adventofcode/blob/2022/apps/aoc2019-day16.hs#L64-L79
2022-12-07 14:12:47 +0100 <kuribas> albet70: either (const $ throw myException) pure
2022-12-07 14:12:56 +0100 <trev> how do you give a type hint to a function? i want to play on the repl with `read` but it doesn't know what type to read into
2022-12-07 14:13:12 +0100 <freeside_> my runtimes are growing by 1, 2, 3, 4, 5, 6 seconds for the same size input
2022-12-07 14:13:15 +0100 <kuribas> :t (id :: Int -> Int) --trev
2022-12-07 14:13:16 +0100 <lambdabot> Int -> Int
2022-12-07 14:13:58 +0100dora(~dora@kwlan4.uoks.uj.edu.pl)
2022-12-07 14:14:33 +0100freeside(~mengwong@103.252.202.193) (Quit: re-nick)
2022-12-07 14:14:43 +0100freeside_freeside
2022-12-07 14:16:52 +0100 <trev> kuribas i don't get it
2022-12-07 14:17:06 +0100 <freeside> so, it appears that an individual run of my `go` function takes a constant 0.01x seconds, but the infrastructure around it (nTimesM) is somehow adding runtime in a way that looks exactly like a memory leak. my process is now up to 24GB :(
2022-12-07 14:17:10 +0100 <trev> how would the identify function work if i don't explicity give it the type?
2022-12-07 14:17:16 +0100 <kuribas> :t (read :: String -> Int)
2022-12-07 14:17:17 +0100 <lambdabot> String -> Int
2022-12-07 14:17:41 +0100 <kuribas> trev: then it determines the type from the context.
2022-12-07 14:17:54 +0100 <freeside> trev: if you want to be explicit about it, see https://github.com/mengwong/adventofcode/blob/0eaef98a90ee886b3ce9fe9ce2eb33336032deeb/apps/aoc202…
2022-12-07 14:18:25 +0100 <trev> i think it works if i just put `:: [Int] ` at the end
2022-12-07 14:18:53 +0100 <freeside> that works too, you can say what the type is of the desired output, and haskell will do type inference to see what the type of read has to be to give you that
2022-12-07 14:19:03 +0100 <trev> :t (map read <$> lines) "1\n2" :: Int
2022-12-07 14:19:04 +0100 <lambdabot> error:
2022-12-07 14:19:04 +0100 <lambdabot> • Couldn't match type ‘[b0]’ with ‘Int’
2022-12-07 14:19:04 +0100 <lambdabot> Expected type: [Char] -> Int
2022-12-07 14:19:47 +0100 <trev> :t (map read <$> lines) "1\n2" :: [Int]
2022-12-07 14:19:48 +0100 <lambdabot> [Int]
2022-12-07 14:20:10 +0100 <trev> lol how do i get it to evaluate here?
2022-12-07 14:20:51 +0100 <trev> % (map read <$> lines) "1\n2" :: [Int]
2022-12-07 14:20:51 +0100 <yahb2> [1,2]
2022-12-07 14:21:03 +0100 <trev> i should've scrolled up cause someone else just did this
2022-12-07 14:23:40 +0100causal(~user@50.35.85.7)
2022-12-07 14:25:42 +0100notzmv(~zmv@user/notzmv)
2022-12-07 14:26:20 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Ping timeout: 260 seconds)
2022-12-07 14:27:01 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 14:27:52 +0100zeenk(~zeenk@2a02:2f04:a30d:4300::7fe)
2022-12-07 14:29:32 +0100 <merijn> freeside: Is this inside ghci?
2022-12-07 14:30:24 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43)
2022-12-07 14:31:22 +0100 <merijn> because while that is not efficient code, it should not blow up to 24GB
2022-12-07 14:32:06 +0100 <kuribas> trev: but as merijn says, better never to use read.
2022-12-07 14:33:23 +0100 <merijn> oh, wait I was looking at the wrong code for the blowup
2022-12-07 14:34:10 +0100 <merijn> freeside: I see at least one memory blow up in your code
2022-12-07 14:34:37 +0100 <merijn> Well, potential one, anyway
2022-12-07 14:35:05 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43) (Ping timeout: 260 seconds)
2022-12-07 14:36:36 +0100 <merijn> ah, actually no. But I do see a good optimisation opportunity, this is horrible: https://github.com/mengwong/adventofcode/blob/2022/apps/aoc2019-day16.hs#L44-L48
2022-12-07 14:36:43 +0100 <merijn> V.fromList is gonna kill you
2022-12-07 14:37:33 +0100 <merijn> freeside: What you want instead of that fromList is to use generate
2022-12-07 14:37:35 +0100 <merijn> https://hackage.haskell.org/package/vector-0.13.0.0/docs/Data-Vector.html#v:generate
2022-12-07 14:37:55 +0100 <kuribas> freeside: those strictness annotations don't look very useful.
2022-12-07 14:38:12 +0100 <merijn> Since you have a fixed vector size and each element is directly generated from the index
2022-12-07 14:38:24 +0100Erutuon(~Erutuon@user/erutuon)
2022-12-07 14:38:51 +0100shriekingnoise(~shrieking@186.137.167.202)
2022-12-07 14:39:06 +0100 <kuribas> freeside: also, if you want performance, don't use "(Monad m) => ..."
2022-12-07 14:40:10 +0100 <kuribas> freeside: IO is already strict
2022-12-07 14:40:25 +0100 <merijn> kuribas: ??
2022-12-07 14:40:35 +0100 <merijn> Not sure if that's relevant, tbh
2022-12-07 14:40:49 +0100 <merijn> and also his Monad m function should trivially specialise in code this simple
2022-12-07 14:41:15 +0100 <merijn> freeside: Also, you should try running this code with "+RTS -sstderr" and see what that says
2022-12-07 14:41:17 +0100azimut(~azimut@gateway/tor-sasl/azimut) (Ping timeout: 255 seconds)
2022-12-07 14:41:48 +0100 <kuribas> merijn: in this case yes
2022-12-07 14:42:17 +0100 <kuribas> freeside: and if you don't need lazy vectors, use unboxed vecors.
2022-12-07 14:42:29 +0100 <kuribas> freeside: they will be an order of magnitude faster.
2022-12-07 14:42:43 +0100 <merijn> oh, yes
2022-12-07 14:43:08 +0100 <merijn> ok, so first thing to try would be: use unboxed vector + V.generate (instead of V.fromList)
2022-12-07 14:43:13 +0100 <merijn> and see how much faster that is
2022-12-07 14:43:44 +0100 <merijn> oh...
2022-12-07 14:43:45 +0100 <merijn> also
2022-12-07 14:43:48 +0100 <kuribas> merijn: "return $! toreturn" doesn't look so useful, or was that for the timing?
2022-12-07 14:44:04 +0100 <merijn> you have a ghc-options field that is a billion miles long, but no -O?
2022-12-07 14:44:14 +0100money_(~money@user/polo) (Quit: money_)
2022-12-07 14:44:54 +0100 <kuribas> maybe he needs to do toreturn `seq` getPOSIXTime instead then?
2022-12-07 14:45:59 +0100acidjnk_new(~acidjnk@p200300d6e7137a66c53ce5ddc06be1e3.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
2022-12-07 14:46:02 +0100 <merijn> kuribas: my comment was mostly that "IO is strict" and "$! probably does nothing there" are completely orthogonal
2022-12-07 14:46:22 +0100 <kuribas> hmm, I suppose so...
2022-12-07 14:47:13 +0100 <merijn> kuribas: IO is not strict in it's return values, so the fact that $! is nothing isn't really related to IO, only to the fact that "at that point the result is probably not big"
2022-12-07 14:47:14 +0100 <kuribas> in any case, toreturn with lazy vec will not be deep forced by $!
2022-12-07 14:47:30 +0100 <kuribas> merijn: fair enough
2022-12-07 14:48:15 +0100 <merijn> I'm not even done with my own AOC for today and I'm already nerdsniped...
2022-12-07 14:48:19 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 14:49:18 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
2022-12-07 14:50:00 +0100 <kuribas> yeah, I should also do my actual job, which is some rather convoluted python code.
2022-12-07 14:51:04 +0100 <dminuoso> 14:08:59 merijn | Sounds like a great way to get lynched by colleagues
2022-12-07 14:51:17 +0100 <dminuoso> Not necessarily, cooking local functions `Maybe a -> IO a` is a very useful thing.
2022-12-07 14:51:33 +0100 <merijn> dminuoso: I was referring to "renaming Either to Exception"
2022-12-07 14:51:36 +0100 <dminuoso> Ah.
2022-12-07 14:51:52 +0100 <kuribas> dminuoso: I do that, but make sure to prefix them with `unsafe`.
2022-12-07 14:52:09 +0100 <dminuoso> Why unsafe?
2022-12-07 14:52:26 +0100 <kuribas> because it can throw an exception.
2022-12-07 14:52:29 +0100 <merijn> People keep wanting to pointlessly rename things non-standard names they are conviced are "better", disregarding that you are now inventing a custom dialect of Haskell that is different from standard Haskell that everyone has to use
2022-12-07 14:52:35 +0100 <dminuoso> IO already denotes the preseence of exceptions.
2022-12-07 14:52:52 +0100 <dminuoso> And in fact, almost every IO action *can* produce exceptions.
2022-12-07 14:53:02 +0100 <merijn> hmmm, I was trying to get baseline performance from the 2019 example
2022-12-07 14:53:02 +0100 <dminuoso> Even something mundane as `putStrLn`
2022-12-07 14:53:10 +0100 <kuribas> yes, one of the biggest haskell flaws
2022-12-07 14:53:11 +0100 <merijn> but I'm not patient enough to wait xD
2022-12-07 14:53:15 +0100 <dminuoso> Not sure about flaw, really.
2022-12-07 14:53:43 +0100 <dminuoso> IO exceptions are great, especially with the extensione hiararchy of exceptions
2022-12-07 14:53:53 +0100 <merijn> dminuoso: You know what would be better?
2022-12-07 14:53:59 +0100 <merijn> dminuoso: Checked IO exceptions! :p
2022-12-07 14:54:04 +0100 <dminuoso> merijn: Sure.
2022-12-07 14:54:20 +0100 <dminuoso> If someone had a *good* way of incorporating that into the type system, Id be game for it.
2022-12-07 14:54:45 +0100 <dminuoso> And by incorporating I dont mean `just enable a bunch of extensions and encode it with type families and all kinds of shenanigans`, but some kind of first class support
2022-12-07 14:55:06 +0100 <merijn> dminuoso: I'm still occasionally working on a sketch for that
2022-12-07 14:55:14 +0100 <merijn> and now I no longer have my thesis distracting me :p
2022-12-07 14:55:19 +0100 <merijn> Just videogames :p
2022-12-07 14:55:21 +0100 <freeside> kuribas: thanks, i am trying a few of your suggestions in turn
2022-12-07 14:55:25 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8)
2022-12-07 14:55:33 +0100 <dminuoso> And even without checked exceptions, IO exceptions are still great.
2022-12-07 14:56:09 +0100 <kuribas> dminuoso: right, those "unsafe" functions where not in IO.
2022-12-07 14:56:12 +0100 <freeside> so, i tried unboxed vectors, and it ran slower, though maybe after I try a few other things, unboxed will be faster.
2022-12-07 14:56:20 +0100 <merijn> freeside: I'm trying to time and memory measure your version, so I can compare improvements, but it's too slow for my patience :p
2022-12-07 14:56:28 +0100 <dminuoso> kuribas: I dont use those. I tend to drag IO very deeply through programs.
2022-12-07 14:56:32 +0100__monty__(~toonn@user/toonn) (Quit: leaving)
2022-12-07 14:56:38 +0100 <dminuoso> Because as it turns out, this is very useful for getting good diagnostics.
2022-12-07 14:56:48 +0100 <dminuoso> And at that point you get nice catch control
2022-12-07 14:57:12 +0100 <dminuoso> And best of all - IO exceptions let you preserve MonadUnliftIO :)
2022-12-07 14:57:22 +0100 <freeside> merijn: i have smaller input sets, if you'd like; i'll check them in.
2022-12-07 14:57:25 +0100 <merijn> dminuoso: People always underestimate how pleasant IO heavy Haskell is :)
2022-12-07 14:58:04 +0100 <kuribas> haskell is the best imperative language :)
2022-12-07 14:58:15 +0100 <dminuoso> merijn: Indeed. It was GHC that actually demonstrated to me how nice it was.
2022-12-07 14:58:23 +0100 <dminuoso> Given that virtuall all of GHC runs in IO
2022-12-07 14:58:48 +0100 <dminuoso> (Yes it has lots of pure code, but it has a very IO centric spine)
2022-12-07 15:00:19 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
2022-12-07 15:01:13 +0100 <freeside> so, the Vec.fromList on line 45, undesirable because, why?
2022-12-07 15:01:20 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Ping timeout: 260 seconds)
2022-12-07 15:01:25 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua)
2022-12-07 15:01:32 +0100 <merijn> freeside: dynamically building vectors of unknown length is expensive
2022-12-07 15:01:40 +0100 <freeside> I can switch it to use a generate -- the genBase function on 31 is basically that already.
2022-12-07 15:01:40 +0100kalj(~kalj@78-71-20-170-no193.tbcn.telia.com) (Quit: Client closed)
2022-12-07 15:01:54 +0100 <merijn> freeside: Because you keep having to reallocate and copy each time your original vector is too small
2022-12-07 15:01:57 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 15:02:03 +0100 <freeside> and then it gets the `n` out of the input by using a simple ! then
2022-12-07 15:02:14 +0100 <merijn> freeside: V.generate takes a static length so it will just allocate and initialise in place once
2022-12-07 15:02:48 +0100 <merijn> Allocate once + fill is always gonna be more efficient than a dynamic approach :)
2022-12-07 15:02:57 +0100 <merijn> It plays nicer with fusion too
2022-12-07 15:03:08 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:897b:5682:aa16:df9e)
2022-12-07 15:03:25 +0100 <dminuoso> How does Data.Vector.fromList work then?
2022-12-07 15:04:43 +0100dora(~dora@kwlan4.uoks.uj.edu.pl) (Ping timeout: 260 seconds)
2022-12-07 15:05:01 +0100 <dminuoso> And shouldnt you be able to use fromListN at least, given that the length is statically known?
2022-12-07 15:05:15 +0100accord(uid568320@id-568320.hampstead.irccloud.com)
2022-12-07 15:05:22 +0100 <merijn> dminuoso: Then you still end up pointlessly creating a list and stuff
2022-12-07 15:05:33 +0100swamp_(~zmt00@user/zmt00)
2022-12-07 15:05:44 +0100 <dminuoso> Fair
2022-12-07 15:05:44 +0100 <merijn> And the actual function here is trivially rewritable as a function of vector index
2022-12-07 15:06:16 +0100 <merijn> (since it's just a function looped over values 1 through l)
2022-12-07 15:06:27 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8)
2022-12-07 15:06:45 +0100 <merijn> So just need to offset it by 1 to work of 0 based indices
2022-12-07 15:07:30 +0100 <dminuoso> Okay so it seems like fromList generates a stream of basicUnsafeWrite, presumably onto a buffer of that is hopefully large enough, otherwise the sequencing will allocate new buffers?
2022-12-07 15:07:53 +0100 <dminuoso> Wouldnt it be cheaper to scan the length of the list first?
2022-12-07 15:08:04 +0100 <merijn> Depends how long your list is
2022-12-07 15:08:14 +0100 <merijn> Also, if your list is giant and lazy that's gonna blow up
2022-12-07 15:08:19 +0100 <freeside> my list has 6.5 million elements
2022-12-07 15:08:23 +0100 <dminuoso> It would blow up regardless on the allocation, no>
2022-12-07 15:08:37 +0100 <freeside> i was hoping that unboxed it would take 6.5 megs in ram
2022-12-07 15:08:49 +0100 <dminuoso> Or is the point that the cons cell is more expensive than potentially the element size in the vector?>
2022-12-07 15:09:08 +0100zmt01(~zmt00@user/zmt00) (Ping timeout: 246 seconds)
2022-12-07 15:09:19 +0100 <merijn> dminuoso: If your vector operations fuse into a Vector.sum, then it doesn't have to
2022-12-07 15:09:22 +0100 <dminuoso> Or even that seems unlikely given that Vector has boxed elements
2022-12-07 15:09:46 +0100 <dminuoso> merijn: is there RULES in place to elide the vector for that?
2022-12-07 15:10:02 +0100 <dminuoso> Ah I guess there must be
2022-12-07 15:10:08 +0100 <dminuoso> That explains the fusion framework then
2022-12-07 15:10:15 +0100 <merijn> dminuoso: That's the entire point of vector's fusion framework, no? :p
2022-12-07 15:10:27 +0100 <dminuoso> Wouldnt know honestly, never looked at vector. :()
2022-12-07 15:10:38 +0100 <merijn> :O
2022-12-07 15:10:40 +0100 <merijn> Vector is nice
2022-12-07 15:11:08 +0100 <dminuoso> Well I mean I use it regularly for some things, but never really looked at what vector was built for or how it works
2022-12-07 15:11:26 +0100 <merijn> overall this solution feels slower than it, naively, should be
2022-12-07 15:11:39 +0100L29Ah(~L29Ah@wikipedia/L29Ah)
2022-12-07 15:12:01 +0100 <merijn> but also, I'm not 100% sure I follow what it's doing, so... :p
2022-12-07 15:12:03 +0100 <dminuoso> Okay so things are falling into place now.
2022-12-07 15:12:04 +0100shapr(~user@68.54.166.125) (Ping timeout: 260 seconds)
2022-12-07 15:12:15 +0100 <dminuoso> Data.Text.pack goes through a stream framework as well
2022-12-07 15:12:17 +0100 <dminuoso> Presumably for the same reason?
2022-12-07 15:12:28 +0100 <freeside> sorry, i should have also shared the original problem. https://adventofcode.com/2019/day/16
2022-12-07 15:12:37 +0100 <freeside> basically, this is a matrix multiplication problem.
2022-12-07 15:12:42 +0100 <dminuoso> "TEXT length/pack -> P.length" forall t. length (pack t) = P.length t
2022-12-07 15:12:46 +0100 <dminuoso> Ah-ha!
2022-12-07 15:12:59 +0100 <dminuoso> Libraries are suddenly starting to make sense. :)
2022-12-07 15:13:00 +0100 <freeside> however, because the matrix is 6.5M x 6.5M, fitting everything into RAM is difficult.
2022-12-07 15:13:09 +0100 <merijn> oh, wait, this is FFT?
2022-12-07 15:13:21 +0100 <freeside> the name of the thing is FFT, but reading the question, i don't think it's FFT.
2022-12-07 15:13:28 +0100 <freeside> it's closer to a repeated block cipher
2022-12-07 15:14:00 +0100 <merijn> Well, one clue is that FFT has recursive sharing between the blocks of a transform
2022-12-07 15:14:27 +0100 <merijn> So I think the problem might be "spot the recursive sharing of your computation" rather than trying to make the naive computation faster
2022-12-07 15:14:44 +0100 <merijn> I think last year had a similar exponential blow up puzzle
2022-12-07 15:17:07 +0100 <merijn> the puzzle formulation seems to also strongly hint at recursive sharing
2022-12-07 15:17:52 +0100 <merijn> I haven't done that one from 2019, but last year's day 14 had an exponential blow up puzzle too and I can show you my solution for that one, maybe it'll trigger some inspiration
2022-12-07 15:18:52 +0100 <freeside> i would be grateful, thank you
2022-12-07 15:19:09 +0100 <merijn> freeside: https://adventofcode.com/2021/day/14 so every iteration becomes longer and longer and the intial version (10 expansions) you can solve by simply having a fast implementation, but the puzzle 2 was 40 expansions and that just runs out of memory trying to handle the full data
2022-12-07 15:20:07 +0100 <merijn> freeside: https://github.com/merijn/AdventOfCode/blob/master/2021/Day14.hs
2022-12-07 15:21:13 +0100freesidelooks
2022-12-07 15:22:21 +0100 <merijn> freeside: The trick for that one was that "the *actual* sequence doesn't matter for what you have to insert or score" so instead of storing the actualy sequence you could just store all possible pairs with a counter of how frequently they occur and every pair produces a (predictable) number of new pairs when you expand, so instead of a billion character sequence you have a Map of pair to count mappings
2022-12-07 15:22:28 +0100 <merijn> and expansion is simply "which new pairs does each original pair expand to and compute new counts for every pair in the new string")
2022-12-07 15:22:39 +0100 <merijn> I expect this day 16 puzzle has a similar trick
2022-12-07 15:22:48 +0100 <merijn> You just gotta find it
2022-12-07 15:22:51 +0100jakalx(~jakalx@base.jakalx.net) (Error from remote client)
2022-12-07 15:23:38 +0100 <merijn> Especially since the entire thing FFT is famous for is being fast due to clever recursive sharing tricks
2022-12-07 15:26:38 +0100 <freeside> gotcha. i guess i've been banging my head against a very particular wall, which is that the runtime is growing quadratically, even though the inner "go" function is running at the same time per round.
2022-12-07 15:27:08 +0100 <merijn> freeside: It took me hours of trying to make my function faster before I realised that last year too
2022-12-07 15:27:25 +0100 <kuribas> freeside: garbage collection?
2022-12-07 15:27:36 +0100 <freeside> i force a performGC at the top of every "go"
2022-12-07 15:27:46 +0100 <merijn> I actually spend *a lot* of effort on my original solution to have a clever streaming solution which was constant space
2022-12-07 15:27:49 +0100 <merijn> And it actually worked
2022-12-07 15:28:00 +0100 <merijn> in that I never had memory blow up, it just took forever to compute xD
2022-12-07 15:28:07 +0100 <merijn> freeside: Actually, what if you don't?
2022-12-07 15:28:07 +0100 <freeside> part of what i'm trying to learn here is how to take maximum advantage of fusion, and how to set up my functions so all the laziness just works
2022-12-07 15:28:22 +0100 <merijn> freeside: unnecessary GC can really fuck you over :p
2022-12-07 15:28:34 +0100 <freeside> hm, ok, let me try a/b testing that next.
2022-12-07 15:29:01 +0100 <merijn> freeside: If you have inputs that finish in reasonable time, try that while passing "+RTS -sstderr"
2022-12-07 15:29:03 +0100 <freeside> i am so glad my M1 macbook air doesn't have a fan, because if it did, it would sound like a jet engine right about now.
2022-12-07 15:29:19 +0100 <merijn> (or "-- +RTS -sstderr" if you use "cabal run", else you pass the flags to cabal :p)
2022-12-07 15:29:23 +0100 <money> mine never goes on
2022-12-07 15:29:40 +0100 <merijn> freeside: That will report GC info and memory usage
2022-12-07 15:30:20 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8) (Remote host closed the connection)
2022-12-07 15:30:23 +0100 <merijn> If you have a big live set (you probably do) GC can waste *a lot* of time
2022-12-07 15:30:51 +0100 <freeside> can i just run stack --profile to get the RTS?
2022-12-07 15:31:00 +0100 <merijn> --profile is different
2022-12-07 15:31:01 +0100 <freeside> i've been using stack run instead of cabal
2022-12-07 15:31:15 +0100 <merijn> freeside: Presumably "-- +RTS -sstderr" works with stack too
2022-12-07 15:31:28 +0100 <freeside> ok, i will incant
2022-12-07 15:31:33 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:897b:5682:aa16:df9e) (Ping timeout: 260 seconds)
2022-12-07 15:31:54 +0100 <merijn> You might need to compile with -rtsopts (i.e. add -rtsopts to you ghc-options)
2022-12-07 15:34:50 +0100ec_(~ec@gateway/tor-sasl/ec) (Ping timeout: 255 seconds)
2022-12-07 15:34:59 +0100elevenkb(~elevenkb@105.184.79.224)
2022-12-07 15:35:27 +0100 <merijn> freeside: The 2 main numbers you wanna be looking at in the output are: max residency (i.e. how much peak memory usage am I having) and productivity (which is
2022-12-07 15:35:39 +0100 <merijn> (which is "time not spend doing GC / total time")
2022-12-07 15:35:57 +0100 <merijn> Productivity below 80% is generally a red flag
2022-12-07 15:36:27 +0100albet70(~xxx@2400:8902::f03c:92ff:fe60:98d8)
2022-12-07 15:36:28 +0100 <merijn> (which is why you wanna test the performGC stuff with the GC reporting, you wanna check it's not wrecking your productivity)
2022-12-07 15:36:34 +0100acidjnk_new(~acidjnk@p200300d6e7137a767ca9aed60fa8d1f2.dip0.t-ipconnect.de)
2022-12-07 15:37:00 +0100ec_(~ec@gateway/tor-sasl/ec)
2022-12-07 15:37:00 +0100jakalx(~jakalx@base.jakalx.net)
2022-12-07 15:41:24 +0100 <freeside> currently fighting with package.yaml to get rtsopts behaving
2022-12-07 15:41:51 +0100 <albet70> is (liftIO x) >> (liftIO y) == liftIO $ x >> y?
2022-12-07 15:42:15 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 15:43:19 +0100 <c_wraith> albet70: did you check the docs?
2022-12-07 15:43:48 +0100 <albet70> not yet
2022-12-07 15:44:05 +0100 <c_wraith> albet70: (yes, it is. But that's something the docs say)
2022-12-07 15:48:45 +0100 <trev> why does it keep telling me that `x` is a Char instead of String? https://paste.tomsmeding.com/zfwaa9wr
2022-12-07 15:48:51 +0100[itchyjunk](~itchyjunk@user/itchyjunk/x-7353470)
2022-12-07 15:48:55 +0100 <albet70> https://hackage.haskell.org/package/conduit-1.3.4.3/docs/Conduit.html#t:MonadIO
2022-12-07 15:49:13 +0100 <albet70> liftIO (m >>= f) = liftIO m >>= (liftIO . f)
2022-12-07 15:51:14 +0100 <albet70> c_wraith , it is >>= not >> in the docs
2022-12-07 15:51:25 +0100 <c_wraith> so use your algebra
2022-12-07 15:51:29 +0100 <c_wraith> it's just a bit of rewriting
2022-12-07 15:52:17 +0100 <c_wraith> m >> n === m >>= \_ -> n
2022-12-07 15:53:33 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 15:53:51 +0100 <dminuoso> trev: Because you pattern match on [x : xs], presumably you meant (x:xs)
2022-12-07 15:54:12 +0100 <money> xxx
2022-12-07 15:54:22 +0100dora(~dora@rivendell.ksi.ii.uj.edu.pl)
2022-12-07 15:54:30 +0100 <trev> O___O
2022-12-07 15:54:33 +0100 <dminuoso> trev: [x:xs] is a deep match, matching on a list of exactly one element, and then matching that one element to a list with at least one element, binding it to `x` and the tail to `xs`
2022-12-07 15:54:38 +0100 <dminuoso> Note that `type String = [Char]`
2022-12-07 15:54:57 +0100 <trev> i actually tried [x:xs] and the formatter kept fixing it LOL
2022-12-07 15:55:01 +0100 <dminuoso> Which is why something like `case "foo" of x:xs -> ...` will work :)
2022-12-07 15:55:16 +0100 <merijn> freeside: You should be able to just edit -rtsopts into the ghc-options in your cabal file
2022-12-07 15:55:23 +0100 <dminuoso> Binding `x` to 'f' and xs to "foo"
2022-12-07 15:55:26 +0100 <dminuoso> "oo" I meant.
2022-12-07 15:55:49 +0100 <merijn> ah, wait you're using hpack
2022-12-07 15:56:00 +0100 <dminuoso> trev: iow "foo" is just syntax sugar for 'f' : 'o' : 'o' : []
2022-12-07 15:56:12 +0100 <trev> dminuoso oh man, i missed that it was a bracket and not parens
2022-12-07 15:56:13 +0100 <merijn> My biased advise would be to just ditch hpack, tbh.
2022-12-07 15:56:20 +0100 <trev> i've been at the computer too long..
2022-12-07 15:56:35 +0100 <trev> dminuoso thank you
2022-12-07 15:56:37 +0100 <freeside> because i am using stack, for my sins, i am trying to `lift` that instruction over hpack's package.yaml
2022-12-07 15:56:49 +0100 <dminuoso> freeside: You can use stack without hpack just fine.
2022-12-07 15:57:01 +0100 <freeside> i will try.
2022-12-07 15:57:53 +0100 <dminuoso> Im not sure why stack defaults to it anyway
2022-12-07 15:58:03 +0100 <dminuoso> The .cabal file format is pretty much fine?
2022-12-07 15:58:20 +0100 <dminuoso> With hpack you need to learn both the hpack syntax *and* the corresponding cabal generated code and semantics.
2022-12-07 15:58:26 +0100 <dminuoso> With cabal.. just the second part.
2022-12-07 15:58:56 +0100 <freeside> yar. let me come back after i have flensed package.yaml from my setup
2022-12-07 15:59:02 +0100 <dminuoso> Not to mention, that you want a .cabal file anyway for non-stack users to use your code...
2022-12-07 15:59:11 +0100 <merijn> freeside: Stack does not require hpack/package.yaml, it just happens to automatically invoke hpack when needed
2022-12-07 15:59:20 +0100 <merijn> dminuoso: to be fair, he has a .cabal file checked in
2022-12-07 16:00:05 +0100 <dminuoso> Im just saying that hpack adds more complication since you need to keep that synchronized.
2022-12-07 16:00:17 +0100shapr(~user@68.54.166.125)
2022-12-07 16:00:32 +0100 <merijn> dminuoso: Yeah, I really dislike hpack and all the people arguing for "we should do cabal in YAML/json/whatever", because inevitably they like the "simple case" and then don't realise you're effectively implementing some custom stringly based format on top of that
2022-12-07 16:00:44 +0100 <merijn> If you're gonna have a custom format it might as well be first class
2022-12-07 16:00:51 +0100 <freeside> oh crap, something changed and now the runtimes are a lot faster, but i'm not sure what changed. one sec while i try to do too many things at once.
2022-12-07 16:01:06 +0100 <dminuoso> "Do it in YAML so you dont need to learn a new format" is one of the absurdest propositions that Ive learned from Ansible long ago.
2022-12-07 16:01:29 +0100Sgeo(~Sgeo@user/sgeo)
2022-12-07 16:01:54 +0100 <dminuoso> Mostly because you still need to learn a special format, because youc ant just write arbitrary YAML and expect it to make sense..
2022-12-07 16:01:56 +0100EvanR(~EvanR@user/evanr) (Remote host closed the connection)
2022-12-07 16:02:18 +0100 <dminuoso> The only difference is that the whitespace layouting rules are clear...
2022-12-07 16:02:22 +0100 <dminuoso> Or uniform.
2022-12-07 16:02:27 +0100EvanR(~EvanR@user/evanr)
2022-12-07 16:02:41 +0100 <merijn> dminuoso: People are still actively arguing for it on github
2022-12-07 16:02:42 +0100 <dminuoso> (But then again, the whitespace rules in YAML are quite absurd)
2022-12-07 16:02:52 +0100 <merijn> So please register your displeasure for the idea >.>
2022-12-07 16:03:04 +0100 <dminuoso> Where on github?
2022-12-07 16:03:56 +0100 <merijn> dminuoso: https://github.com/haskell/cabal/issues/8605 https://github.com/haskell/cabal/issues/7548
2022-12-07 16:05:06 +0100akegalj(~akegalj@180-243.dsl.iskon.hr)
2022-12-07 16:06:11 +0100 <merijn> obligatory "I implemented a TOML to cabal program!" that then only uses 10% of the syntax/feature of cabal files >.>
2022-12-07 16:07:46 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Ping timeout: 256 seconds)
2022-12-07 16:08:38 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 16:11:00 +0100kenran(~user@user/kenran)
2022-12-07 16:12:11 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Client Quit)
2022-12-07 16:12:58 +0100kenran(~user@user/kenran) (Remote host closed the connection)
2022-12-07 16:13:17 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 16:21:22 +0100foul_owl(~kerry@193.29.61.77) (Ping timeout: 256 seconds)
2022-12-07 16:21:37 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 16:25:13 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 260 seconds)
2022-12-07 16:28:50 +0100 <freeside> woohoo! i figured out RTS, and now i have output: https://github.com/mengwong/adventofcode/commit/71d6e5a83f092c58aee8126ed31a05b600c8b80d#commitcom…
2022-12-07 16:29:22 +0100 <freeside> am tempted to turn on profiling and draw the heap profile using hp2ps
2022-12-07 16:30:34 +0100 <freeside> 3,097,783,264 bytes maximum residency
2022-12-07 16:30:39 +0100 <freeside> Productivity 1.2% of total user, 6.7% of total elapsed
2022-12-07 16:31:22 +0100 <freeside> rerunning with performGC disabled
2022-12-07 16:32:25 +0100 <freeside> 3,002,958,440 bytes maximum residency
2022-12-07 16:32:30 +0100 <freeside> Productivity 15.6% of total user, 11.6% of total elapsed
2022-12-07 16:32:36 +0100 <freeside> we must trust the garbage collector
2022-12-07 16:34:46 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 16:35:45 +0100 <freeside> the full-size run is still taking up too much ram, though: why does it need more than 6.5M, or even with 32-bit integers, why does it need more than 26 megs of ram?
2022-12-07 16:35:46 +0100 <merijn> freeside: ok, so productivity of 15% is clearly better, but still *atrocious*
2022-12-07 16:35:50 +0100foul_owl(~kerry@157.97.134.158)
2022-12-07 16:35:56 +0100 <merijn> freeside: It means 85% of your runtime is GC :p
2022-12-07 16:37:27 +0100 <merijn> freeside: Is that with unboxed or just as-is?
2022-12-07 16:37:41 +0100 <int-e> that's quite a lot of residency.
2022-12-07 16:38:19 +0100 <freeside> this is boxed
2022-12-07 16:38:34 +0100 <freeside> i feel like some of the consumed data is still lingering
2022-12-07 16:38:38 +0100 <merijn> freeside: boxed is gonna add *minimum* 8 bytes per item
2022-12-07 16:38:49 +0100 <merijn> (extra pointer indirection)
2022-12-07 16:39:38 +0100 <freeside> i will rerun unboxed
2022-12-07 16:40:19 +0100 <merijn> I'm wondering if the input string is kept alive
2022-12-07 16:40:52 +0100 <merijn> but that shouldn't be that expensive
2022-12-07 16:41:08 +0100 <freeside> the really weird thing now is my last run hung at "answer: ", which suggests some laziness is still being resolved
2022-12-07 16:41:21 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Quit: No Ping reply in 180 seconds.)
2022-12-07 16:42:13 +0100 <freeside> running unboxed is a lot slower, but the RAM is staying under 13MB, so that's a relief.
2022-12-07 16:42:27 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 16:44:52 +0100 <merijn> Interesting
2022-12-07 16:45:09 +0100 <merijn> Are you using -O or -O2 now, btw?
2022-12-07 16:46:01 +0100 <freeside> er, i don't know, possibly neither?
2022-12-07 16:46:25 +0100 <merijn> ah, yeah, you're not, so that's probably another thing to do :p
2022-12-07 16:46:51 +0100 <merijn> Just add -O (or -O2) to ghc-options in the cabal file
2022-12-07 16:47:10 +0100 <merijn> freeside: Without that the optimiser isn't enabled and especially for numeric heavy code that can matter A LOT
2022-12-07 16:47:28 +0100 <freeside> anyway, now is the time to start optimizing based on the actual features of the problem, as you suggested. there are a ton of optimizations opportunities, not least of which is that most of the computations can be reduced from a multiplication to a lookup, and on top of that, most of the computations don't even need to be repeated, because half the base matrix is 0's, in a very predictable way
2022-12-07 16:49:33 +0100 <c_wraith> I though cabal defaulted to -O until you specify otherwise
2022-12-07 16:50:14 +0100 <merijn> c_wraith: depends on what's in your config, I guess
2022-12-07 16:50:18 +0100lortabac(~lortabac@2a01:e0a:541:b8f0:ebf5:c68c:db4f:4f95) (Quit: WeeChat 2.8)
2022-12-07 16:50:27 +0100 <c_wraith> *thought
2022-12-07 16:50:37 +0100 <c_wraith> anyway, default meaning "if you don't specify"
2022-12-07 16:55:21 +0100 <freeside> yeah, i'm pretty sure the Boxed computations are being thunked, even though I had LANGUAGE Strict.
2022-12-07 16:55:32 +0100 <int-e> oh that problem... there's a really stupid thing about it
2022-12-07 16:56:43 +0100 <c_wraith> -XStrict does not prevent thunks.
2022-12-07 16:56:46 +0100 <c_wraith> that's not what it's for
2022-12-07 16:57:04 +0100 <c_wraith> The ghc user guide explains pretty explicitly what it does
2022-12-07 16:57:36 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 16:59:59 +0100 <c_wraith> As usual, I strongly recommend learning how evaluation works and writing code that explicitly evaluates what is necessary and doesn't evaluate anything else.
2022-12-07 17:01:20 +0100 <merijn> -XStrict is so overhyped
2022-12-07 17:01:22 +0100 <c_wraith> I've been burned so many times by libraries breaking my code with too much strict evaluation.
2022-12-07 17:01:31 +0100 <merijn> There is no way to avoid thinking about strictness
2022-12-07 17:01:39 +0100dsrt^(~dsrt@76.145.185.103) (Remote host closed the connection)
2022-12-07 17:01:51 +0100 <merijn> -XStrict is not a magical solution, it just swaps the default to an (arguably) stupider one
2022-12-07 17:02:11 +0100 <DigitalKiwi> ahem i avoid it by not thinking
2022-12-07 17:03:11 +0100 <c_wraith> I guess core-ish libraries stopped adding incorrect strictness in patch updates about 10 years ago now, but there was an annoying period of time in there when it was common
2022-12-07 17:05:37 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43)
2022-12-07 17:07:05 +0100acidjnk_new(~acidjnk@p200300d6e7137a767ca9aed60fa8d1f2.dip0.t-ipconnect.de) (Ping timeout: 256 seconds)
2022-12-07 17:09:54 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 17:10:54 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 17:11:18 +0100dora(~dora@rivendell.ksi.ii.uj.edu.pl) (Ping timeout: 260 seconds)
2022-12-07 17:12:23 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt) (Ping timeout: 246 seconds)
2022-12-07 17:12:48 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt)
2022-12-07 17:12:50 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 17:15:09 +0100tomku(~tomku@user/tomku) (Ping timeout: 260 seconds)
2022-12-07 17:21:17 +0100MajorBiscuit(~MajorBisc@c-001-003-046.client.tudelft.eduvpn.nl) (Quit: WeeChat 3.6)
2022-12-07 17:28:40 +0100zeenk(~zeenk@2a02:2f04:a30d:4300::7fe) (Quit: Konversation terminated!)
2022-12-07 17:29:29 +0100 <maerwald> I work in a strict Haskell dialect, so not sure I agree
2022-12-07 17:36:38 +0100tomku(~tomku@user/tomku)
2022-12-07 17:37:39 +0100alexiscott(~user@4.red-83-36-45.dynamicip.rima-tde.net) (Ping timeout: 268 seconds)
2022-12-07 17:37:52 +0100nschoe(~q@141.101.51.197) (Ping timeout: 256 seconds)
2022-12-07 17:39:55 +0100fserucas(~fserucas@laubervilliers-657-1-66-228.w90-63.abo.wanadoo.fr) (Ping timeout: 252 seconds)
2022-12-07 17:41:48 +0100bobbingbob(~dfadsva@2604:3d09:207f:f650::7b3a)
2022-12-07 17:43:56 +0100euandreh(~Thunderbi@179.214.113.107) (Quit: euandreh)
2022-12-07 17:47:02 +0100Lycurgus(~juan@user/Lycurgus)
2022-12-07 17:49:50 +0100califax(~califax@user/califx) (Ping timeout: 255 seconds)
2022-12-07 17:49:57 +0100califax_(~califax@user/califx)
2022-12-07 17:51:10 +0100califax_califax
2022-12-07 17:53:09 +0100Topsi(~Topsi@217.64.164.1) (Quit: Client closed)
2022-12-07 17:54:58 +0100 <bobbingbob> im interested in Data.Sum but don't really understand it. Any willing to point to or give an explanation?
2022-12-07 17:55:30 +0100 <bobbingbob> i want to try it out for a extensible widget system for my gui. Does this sound like a reasonable application?
2022-12-07 17:56:47 +0100Xeroine(~Xeroine@user/xeroine) (Ping timeout: 260 seconds)
2022-12-07 17:58:47 +0100Xeroine(~Xeroine@user/xeroine)
2022-12-07 18:02:56 +0100michalz(~michalz@185.246.204.75) (Remote host closed the connection)
2022-12-07 18:05:53 +0100econo(uid147250@user/econo)
2022-12-07 18:05:56 +0100CiaoSen(~Jura@p200300c95747e0002a3a4dfffe84dbd5.dip0.t-ipconnect.de) (Ping timeout: 246 seconds)
2022-12-07 18:06:22 +0100michalz(~michalz@185.246.204.77)
2022-12-07 18:07:04 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43) (Remote host closed the connection)
2022-12-07 18:07:08 +0100 <merijn> What is Data.Sum?
2022-12-07 18:07:44 +0100opticblast(~Thunderbi@secure-165.caltech.edu)
2022-12-07 18:08:35 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 18:08:41 +0100 <bobbingbob> so you know the open union type stuff in oleg's effect stuff? this is that part by itself
2022-12-07 18:09:14 +0100 <bobbingbob> im wondering if it could be used for a hetergenous collection
2022-12-07 18:09:35 +0100 <bobbingbob> or maybe im wildy misunderstanding things
2022-12-07 18:09:40 +0100 <[exa]> bobbingbob: you meant Data.Functor.Sum ?
2022-12-07 18:10:22 +0100 <bobbingbob> [exa]: i mean the package fastsum
2022-12-07 18:10:45 +0100 <[exa]> ah
2022-12-07 18:10:56 +0100Guest|56(~Guest|56@ip241-94-176-143.adsl2.static.versatel.nl)
2022-12-07 18:11:38 +0100Guest|56(~Guest|56@ip241-94-176-143.adsl2.static.versatel.nl) (Client Quit)
2022-12-07 18:13:20 +0100 <bobbingbob> i going to reread the effects paper. i vaguely understood the early portions. i think i will do my own mock implementation
2022-12-07 18:13:43 +0100 <[exa]> bobbingbob: the Sum is created to make types that have a list of various properties typically with no particular order. You don't need that even remotely for doing heterogeneous collections
2022-12-07 18:14:24 +0100Lycurgus(~juan@user/Lycurgus) (Quit: Exeunt https://tinyurl.com/4m8d4kd5)
2022-12-07 18:14:29 +0100 <bobbingbob> ok so i would do better with GADTs
2022-12-07 18:14:38 +0100 <[exa]> re "various properties" you might think of "may satisfy many Constraints"
2022-12-07 18:14:49 +0100 <[exa]> do you know how `mtl` or `transformers` work?
2022-12-07 18:14:59 +0100 <bobbingbob> not in depth
2022-12-07 18:14:59 +0100accord(uid568320@id-568320.hampstead.irccloud.com) (Quit: Connection closed for inactivity)
2022-12-07 18:15:30 +0100 <bobbingbob> there is a simple monad stack in repa-V4l2 that i looked at
2022-12-07 18:15:50 +0100 <bobbingbob> i understand the lifting
2022-12-07 18:16:27 +0100 <bobbingbob> i will look for some papers on monad transformers
2022-12-07 18:16:34 +0100bgs(~bgs@212-85-160-171.dynamic.telemach.net) (Remote host closed the connection)
2022-12-07 18:16:36 +0100 <[exa]> one use of this is (VERY ROUGLY) to write something like `MagicEffectMonad [HasState x, HasReader y, HasIO, ...] a` instead of `StateT x (ReaderT y (.... IO )) a`
2022-12-07 18:18:27 +0100 <[exa]> a typical problem with monad transformers is that they unwrap (are interpreted) by layers which may be impractical, interpretation of this kind of extensible effects is ... impractical differently. :D
2022-12-07 18:19:58 +0100 <Hecate> bgamari: you should show Andres Löh this, he would love it for his workshops: https://social.treehouse.systems/@armael/109473361778060633
2022-12-07 18:21:03 +0100 <Hecate> ah silly me, he's kosmikus
2022-12-07 18:22:06 +0100 <bgamari[m]> Hecate: indeed
2022-12-07 18:22:56 +0100 <bgamari[m]> Hecate: do you know about https://hackage.haskell.org/package/ghc-heap-view
2022-12-07 18:23:12 +0100phill96(~phill@2600:8807:8100:1e:fddd:78c0:9f78:c96f)
2022-12-07 18:23:22 +0100Tuplanolla(~Tuplanoll@91-159-68-152.elisa-laajakaista.fi)
2022-12-07 18:23:22 +0100phill96ph_l
2022-12-07 18:24:20 +0100ubert1(~Thunderbi@2a02:8109:abc0:6434:3dae:2edc:412:e26e) (Ping timeout: 256 seconds)
2022-12-07 18:24:24 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 18:29:19 +0100razetime(~quassel@49.207.203.213) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.)
2022-12-07 18:29:51 +0100razetime(~quassel@49.207.203.213)
2022-12-07 18:33:51 +0100mestre(~mestre@191.177.185.178)
2022-12-07 18:34:59 +0100 <fendor[m]> can data families only be used with fully saturated type constructors? I want to have `data family Scope f`, where the kind of `f` is `Type -> Type -> Type`
2022-12-07 18:35:14 +0100 <fendor[m]> actually just `Type -> Type`, but same thing
2022-12-07 18:37:56 +0100 <fendor[m]> ah, that seems to require an explicit kind signature
2022-12-07 18:38:49 +0100 <fendor[m]> a stand alone kind signature to be precise.
2022-12-07 18:45:12 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 18:46:15 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 18:48:23 +0100razetime(~quassel@49.207.203.213) (Quit: https://quassel-irc.org - Chat comfortably. Anywhere.)
2022-12-07 18:49:52 +0100notzmv(~zmv@user/notzmv) (Ping timeout: 265 seconds)
2022-12-07 18:50:42 +0100kuribas(~user@ptr-17d51eo0qm84xeejuqw.18120a2.ip6.access.telenet.be) (Quit: ERC (IRC client for Emacs 27.1))
2022-12-07 18:50:47 +0100son0p(~ff@2604:3d08:5b7f:5540::a58f) (Ping timeout: 256 seconds)
2022-12-07 18:51:35 +0100jakalx(~jakalx@base.jakalx.net) (Error from remote client)
2022-12-07 18:52:02 +0100wootehfoot(~wootehfoo@user/wootehfoot)
2022-12-07 18:52:27 +0100 <merijn> man...megaparsec used to be so easy, why did the docs become such a mess :\
2022-12-07 18:53:20 +0100 <merijn> Can't even find out how to parse a word
2022-12-07 18:58:18 +0100azimut(~azimut@gateway/tor-sasl/azimut)
2022-12-07 18:58:34 +0100jakalx(~jakalx@base.jakalx.net)
2022-12-07 19:05:15 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43)
2022-12-07 19:09:08 +0100ph_l(~phill@2600:8807:8100:1e:fddd:78c0:9f78:c96f) (Ping timeout: 260 seconds)
2022-12-07 19:11:10 +0100mbuf(~Shakthi@49.204.118.69) (Quit: Leaving)
2022-12-07 19:13:17 +0100 <sm> merijn: I think it's when it outsourced generic combinators to another package
2022-12-07 19:13:41 +0100 <merijn> sm: That's not a generic combinator, though
2022-12-07 19:14:01 +0100 <merijn> But it turns out takeWhileP is what I wanted, but couldn't find
2022-12-07 19:15:46 +0100manwithluck(~manwithlu@194.177.28.176) (Remote host closed the connection)
2022-12-07 19:15:47 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Ping timeout: 255 seconds)
2022-12-07 19:16:21 +0100chele(~chele@user/chele) (Quit: Leaving)
2022-12-07 19:16:29 +0100 <sm> megaparsec's docs are above average, but there's always room for improvement I guess
2022-12-07 19:17:41 +0100eggplantade(~Eggplanta@2600:1700:38c5:d800:30d2:fcaf:3b1c:ad43) (Remote host closed the connection)
2022-12-07 19:17:54 +0100 <sm> would some letterChar have worked ?
2022-12-07 19:18:23 +0100akegalj(~akegalj@180-243.dsl.iskon.hr) (Ping timeout: 246 seconds)
2022-12-07 19:18:46 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 19:19:48 +0100elevenkb(~elevenkb@105.184.79.224) (Quit: Client closed)
2022-12-07 19:22:15 +0100 <tomsmeding> 11:35 <dminuoso> Not sure why weechat does occacsionally print `- - - - - - ...`
2022-12-07 19:22:43 +0100 <tomsmeding> that's definitely the last-position-before-switch marker, i.e. you've "seen" the messages until there before you switched away from the buffer
2022-12-07 19:23:03 +0100 <tomsmeding> not sure how this mechanic works if you have multiple buffers on screen, but with one full-screen buffer it's very predictable
2022-12-07 19:25:00 +0100pavonia(~user@user/siracusa) (Quit: Bye!)
2022-12-07 19:29:32 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:4d39:d844:8601:6cb2)
2022-12-07 19:29:38 +0100 <o1lo01ol1o> I have an hspec test in a suite that fails when run in cabal test but which passes in ghci. Are there any resources for what may be going on?
2022-12-07 19:29:53 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 19:30:20 +0100coot(~coot@213.134.171.3) (Quit: coot)
2022-12-07 19:30:51 +0100 <o1lo01ol1o> what's wierd is that it doesn't provide an error, it looks like a forked process died.  But i'm not running in parallel and the test is pure, so i don't know why that would be.
2022-12-07 19:33:57 +0100 <Chai-T-Rex> Are there any recommended VS Code extensions for programming in Haskell?
2022-12-07 19:34:51 +0100 <sm> Haskell
2022-12-07 19:35:35 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt) (Ping timeout: 264 seconds)
2022-12-07 19:36:48 +0100 <sm> o1lo01ol1o: ghci runs in a different mode than compiled code. Are there threads involved, eg ?
2022-12-07 19:37:21 +0100 <o1lo01ol1o> sm: there are no threads involved.  it's a JSON round-trip test
2022-12-07 19:37:55 +0100 <sm> is it pure haskell, or calling out to a C lib ?
2022-12-07 19:38:00 +0100 <o1lo01ol1o> pure haskell
2022-12-07 19:38:31 +0100 <o1lo01ol1o> it's literally serializing a recurisve datatype using Aeson and deserializing it again
2022-12-07 19:38:48 +0100 <sm> mystery.. remove bits until it works I guess
2022-12-07 19:39:28 +0100 <o1lo01ol1o> but it's already fairly minimal, the current test has like 15 terms.
2022-12-07 19:39:45 +0100 <o1lo01ol1o> it works without a hitch in ghci
2022-12-07 19:40:24 +0100eggplantade(~Eggplanta@104-55-37-220.lightspeed.sntcca.sbcglobal.net)
2022-12-07 19:40:55 +0100 <sm> nevertheless.. my Excellent Debugging Technique Of Success is guaranteed!
2022-12-07 19:41:11 +0100son0p(~ff@s0106f88b37df247a.vn.shawcable.net)
2022-12-07 19:41:18 +0100 <o1lo01ol1o> sm: :plus 1"
2022-12-07 19:41:37 +0100 <mauke> strace -f
2022-12-07 19:42:02 +0100smsucks in breath sharply... a challenger!
2022-12-07 19:42:12 +0100 <sm> it is powerful!
2022-12-07 19:43:19 +0100 <sm> and I guess the same package versions are being used in both cases
2022-12-07 19:43:56 +0100 <o1lo01ol1o> sm: it's in nix, everything is pinned
2022-12-07 19:44:36 +0100haritz(~hrtz@82-69-11-11.dsl.in-addr.zen.co.uk)
2022-12-07 19:44:37 +0100haritz(~hrtz@82-69-11-11.dsl.in-addr.zen.co.uk) (Changing host)
2022-12-07 19:44:37 +0100haritz(~hrtz@user/haritz)
2022-12-07 19:44:38 +0100 <sm> sure, but... are you running ghci via cabal repl ?
2022-12-07 19:44:44 +0100 <o1lo01ol1o> yes
2022-12-07 19:45:09 +0100 <sm> cool, cool
2022-12-07 19:47:30 +0100gurkenglas(~gurkengla@p548ac72e.dip0.t-ipconnect.de)
2022-12-07 19:48:17 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt)
2022-12-07 19:48:37 +0100jle``(~jusle@user/jle/x-3894663) (Quit: WeeChat 3.6)
2022-12-07 19:50:24 +0100manwithluck(~manwithlu@194.177.28.176)
2022-12-07 19:52:44 +0100beteigeuze(~Thunderbi@bl14-81-220.dsl.telepac.pt) (Ping timeout: 256 seconds)
2022-12-07 19:54:41 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 19:55:13 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 19:59:52 +0100raehik(~raehik@cpc95906-rdng25-2-0-cust156.15-3.cable.virginm.net) (Ping timeout: 252 seconds)
2022-12-07 20:01:24 +0100zant1(~zant@62.96.232.178) (Ping timeout: 260 seconds)
2022-12-07 20:03:24 +0100tomokojun(~tomokojun@static-198-54-134-86.cust.tzulo.com)
2022-12-07 20:03:40 +0100tzh(~tzh@c-24-21-73-154.hsd1.or.comcast.net)
2022-12-07 20:03:56 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 20:05:43 +0100o1lo01ol1o(~o1lo01ol1@2001:8a0:6a54:cb00:4d39:d844:8601:6cb2) (Ping timeout: 260 seconds)
2022-12-07 20:08:25 +0100 <Chai-T-Rex> sm: Thanks.
2022-12-07 20:12:30 +0100Guest75(Guest75@2a01:7e01::f03c:92ff:fe5d:7b18)
2022-12-07 20:13:41 +0100 <Guest75> Hello! I have my home machine (where it works ok), but on the server where I build the project this: https://github.com/andrewboltachev/pyparts/blob/master/app/Main.hs#L42
2022-12-07 20:13:55 +0100 <Guest75> is giving "Perhaps this statement should be within a 'do' block?" error
2022-12-07 20:13:59 +0100 <gurkenglas> [Leary]: nope! but it's close in spirit
2022-12-07 20:14:11 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 20:14:17 +0100 <Guest75> what versions (ghci etc) or whitespace settings should I check in order for it to work?
2022-12-07 20:15:44 +0100acidjnk_new(~acidjnk@p200300d6e7137a767ca9aed60fa8d1f2.dip0.t-ipconnect.de)
2022-12-07 20:18:28 +0100 <Guest75> UPD: sorry, "stack build" command doesn't work on local machine either
2022-12-07 20:19:51 +0100 <dminuoso> tomsmeding: Things you learn. Mmm
2022-12-07 20:19:52 +0100 <Guest75> fixed ws and it works.
2022-12-07 20:20:28 +0100 <dminuoso> Guest75: By the way, the marked line has some very quirky parenthesis style.
2022-12-07 20:20:49 +0100 <dminuoso> Consider writing `(m2e "JSON root element must be a map") $ asKeyMap b` as: m2e "JSON root element must be a map" (asKeyMap b)
2022-12-07 20:21:47 +0100 <Guest75> yes, such caveats are what I'm always afraid of
2022-12-07 20:22:11 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 265 seconds)
2022-12-07 20:22:48 +0100 <dminuoso> There's a great way to avoid many of the quirky ways: Just avoid using $ entirely. The few commonly agreed upon legit uses have disappeared with -XBlockArguments, the others are situational and probably better done with parenthesis and/or function composition instead.
2022-12-07 20:23:28 +0100Guest75(Guest75@2a01:7e01::f03c:92ff:fe5d:7b18) (Quit: Client closed)
2022-12-07 20:24:10 +0100Guest75(~Guest75@192.46.237.51)
2022-12-07 20:24:13 +0100 <Guest75> Will <$> and <*> also disappear?
2022-12-07 20:24:42 +0100doyougnu(~doyougnu@cpe-74-69-132-225.stny.res.rr.com)
2022-12-07 20:24:50 +0100 <Guest75> Not sure if <*> has prefix version though
2022-12-07 20:24:56 +0100 <dsal> Someone at work has being using `do` in place of `$` and it just looks irrationally offensive to me.
2022-12-07 20:25:04 +0100 <dsal> :t ap
2022-12-07 20:25:05 +0100 <lambdabot> Monad m => m (a -> b) -> m a -> m b
2022-12-07 20:25:19 +0100crazazy(~user@130.89.171.62)
2022-12-07 20:26:06 +0100[exa]foresees -XBlockDollar
2022-12-07 20:26:10 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 256 seconds)
2022-12-07 20:26:19 +0100 <Guest75> ah yes, ap
2022-12-07 20:26:20 +0100 <Guest75> lol
2022-12-07 20:26:43 +0100 <dsal> Hopefully we can still use ¢
2022-12-07 20:30:46 +0100 <romes[m]> I was reading on custom memory allocators and was now wondering whether GHC's RTS could benefit from them
2022-12-07 20:31:17 +0100 <romes[m]> As in "malloc and free are very slow operations so we should create our own custom memory allocator" :)
2022-12-07 20:31:27 +0100 <romes[m]> Wondering if anyone's thought about those things
2022-12-07 20:31:33 +0100 <c_wraith> dminuoso: don't make me use lambdas instead of right sections of $
2022-12-07 20:31:46 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua) (Ping timeout: 252 seconds)
2022-12-07 20:32:05 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10) (Ping timeout: 260 seconds)
2022-12-07 20:32:21 +0100 <romes[m]> > "Keep heap allocations to a minimum, and never allocate from the heap within a tight loop."
2022-12-07 20:32:23 +0100 <lambdabot> "Keep heap allocations to a minimum, and never allocate from the heap within...
2022-12-07 20:32:23 +0100 <c_wraith> romes[m]: why do you think GHC uses malloc and free?
2022-12-07 20:33:24 +0100 <dsal> Functional programming languages are garbage producers.
2022-12-07 20:33:36 +0100 <romes[m]> c_wraith: I was grepping for it. From what I got, all memory allocations are done through stgMalloc with the exception of some three uses in fs.c
2022-12-07 20:33:41 +0100 <romes[m]> stgMalloc wraps malloc
2022-12-07 20:33:46 +0100 <festive_kurbus> dsal: they're not gonna like that one
2022-12-07 20:33:51 +0100 <geekosaur> you got wrong
2022-12-07 20:34:32 +0100 <mauke> all memory allocations are done through malloc if you grep -i malloc
2022-12-07 20:34:40 +0100 <dminuoso> c_wraith: Heh.
2022-12-07 20:34:49 +0100irrgit__(~irrgit@86.106.90.226) (Read error: Connection reset by peer)
2022-12-07 20:35:08 +0100 <romes[m]> maybe I'm searching in the wrong place (rts/)
2022-12-07 20:35:14 +0100son0p(~ff@s0106f88b37df247a.vn.shawcable.net) (Ping timeout: 256 seconds)
2022-12-07 20:35:45 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 20:36:17 +0100 <geekosaur> since ghc7ish ghc has been using a 2-stage page-based allocator on 64 bit platforms
2022-12-07 20:36:54 +0100 <romes[m]> Cool!
2022-12-07 20:36:57 +0100 <romes[m]> (note: I was really just asking if it's been thought of, not affirming it's not)
2022-12-07 20:37:30 +0100 <dminuoso> https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/rts/storage
2022-12-07 20:37:32 +0100 <dminuoso> https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/rts/storage/block-alloc
2022-12-07 20:37:38 +0100 <dminuoso> These may be of interest to you
2022-12-07 20:37:48 +0100 <romes[m]> Reading... Thanks!
2022-12-07 20:38:23 +0100 <dsal> dtrace and similar are pretty good for answering these kinds of questions. You can observe all the calls to malloc when deciding how much it will improve things.
2022-12-07 20:38:47 +0100 <gurkenglas> Control.Exception uses its isDoesNotExistError example two times, but doesn't actually export isDoesNotExistError? :(
2022-12-07 20:39:06 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 20:39:09 +0100 <dminuoso> tomsmeding: Take note that the wiki articles, the ones linked in particular, contain links to relevant source files at the top.
2022-12-07 20:39:16 +0100 <mauke> :t isDoesNotExistError
2022-12-07 20:39:17 +0100 <lambdabot> error:
2022-12-07 20:39:17 +0100 <lambdabot> Variable not in scope: isDoesNotExistError
2022-12-07 20:39:43 +0100 <gurkenglas> mauke, I regret to inform you that this identifier
2022-12-07 20:39:46 +0100 <gurkenglas> doesn't exist
2022-12-07 20:39:57 +0100 <dminuoso> gurkenglas: It's from System.IO.Error
2022-12-07 20:40:02 +0100 <mauke> YEEAAAAHHH
2022-12-07 20:40:32 +0100 <gurkenglas> oh, silly of me
2022-12-07 20:42:10 +0100 <dminuoso> Control.Exception is just the generic exception interface, with System.IO.Error defining IOError and relating utilities.
2022-12-07 20:42:53 +0100 <gurkenglas> typecheck: "Perhaps you want to add ‘SomeException’ to the import list in the import of ‘Control.Exception’"
2022-12-07 20:42:55 +0100Erutuon(~Erutuon@user/erutuon) (Ping timeout: 260 seconds)
2022-12-07 20:42:56 +0100irrgit_(~irrgit@176.113.74.74)
2022-12-07 20:42:57 +0100 <gurkenglas> hls: "No quick fixes available"
2022-12-07 20:44:21 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 20:44:23 +0100sammelweis(~quassel@2601:401:8200:2d4c:bd9:d04c:7f69:eb10)
2022-12-07 20:45:09 +0100 <gurkenglas> how come doesNotExistError is identified at runtime instead of on the type level :(
2022-12-07 20:45:50 +0100 <festive_kurbus> because skill issue
2022-12-07 20:46:14 +0100 <dminuoso> You could in principle do it with catch, but that would require extending the hierarchy
2022-12-07 20:46:31 +0100 <geekosaur[m]> Because sane people write type level programs in Idris, not Haskell
2022-12-07 20:47:24 +0100Erutuon(~Erutuon@user/erutuon)
2022-12-07 20:47:32 +0100 <mauke> inb4 type-level catch
2022-12-07 20:47:35 +0100 <dminuoso> gurkenglas: Besides, IOException is a conceptual mapping to the standard errno error codes.
2022-12-07 20:47:51 +0100 <dminuoso> (Or the errno interface in general)
2022-12-07 20:48:01 +0100avicenzi(~avicenzi@2a00:ca8:a1f:b004::c32) (Ping timeout: 252 seconds)
2022-12-07 20:48:02 +0100 <dminuoso> It's very low level and simple, probably for historic reasons.
2022-12-07 20:48:18 +0100 <gurkenglas> dminuoso: the problem with moving the "there are n values per type" to "there are n types with one value each" is something to do with Haskell's superclass system?
2022-12-07 20:48:43 +0100 <dminuoso> gurkenglas: well we can do the latter in exceptions actually
2022-12-07 20:48:46 +0100 <dminuoso> with full subtyping.
2022-12-07 20:48:54 +0100 <dminuoso> but it doesnt work with superclasses
2022-12-07 20:49:05 +0100 <dminuoso> https://simonmar.github.io/bib/papers/ext-exceptions.pdf
2022-12-07 20:49:25 +0100 <dminuoso> It's a wonderful mechanism that GHC uses to some extend, but is widely underappreciated.
2022-12-07 20:49:41 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl)
2022-12-07 20:50:02 +0100 <dminuoso> Think of it as java-style exceptions, with being able to catch a parent or child exception type (except they are not checked)
2022-12-07 20:51:39 +0100 <dminuoso> It's just that for one reason or another the IOException sub-exceptions do not use this mechanism.
2022-12-07 20:52:08 +0100coot(~coot@2a02:a310:e241:1b00:ec1a:e9df:79ac:66ba)
2022-12-07 20:52:15 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 20:52:38 +0100 <gurkenglas> How do I make goto definition work on definitions imported from libraries in hls?
2022-12-07 20:52:48 +0100 <dminuoso> You could easily just make `DoesNotExistError`, `AlreadyInUseError`, etc and tie them into the hierarchy, such that catching `IOException` will still get them all, but you can directly just catch IOException (without having to use a predicate like isDoesNotExistError and rethrowing)
2022-12-07 20:53:18 +0100mestre(~mestre@191.177.185.178) (Quit: Lost terminal)
2022-12-07 20:54:37 +0100 <dminuoso> The main difficulty would be just migrating codebases that directly build an IOException from hand, which probably happens outside GHC/base/haskell libraries as well.
2022-12-07 20:55:05 +0100maukediscovers BlockArguments, falls in love
2022-12-07 20:55:37 +0100 <gurkenglas> are there plans to let any such API changes come with a codebase migrator?
2022-12-07 20:56:14 +0100doyougnu(~doyougnu@cpe-74-69-132-225.stny.res.rr.com) (Ping timeout: 260 seconds)
2022-12-07 20:56:16 +0100 <dminuoso> No. Mostly its just some written notes in the gitlab wiki, and deprecation warnings (that people barely read because nobody enables -Wcompat)
2022-12-07 20:56:33 +0100beteigeuze(~Thunderbi@a79-169-109-107.cpe.netcabo.pt)
2022-12-07 20:56:38 +0100 <dminuoso> Things will then break after the long grace periods that we grant, frustrating users...
2022-12-07 20:57:32 +0100beteigeuze(~Thunderbi@a79-169-109-107.cpe.netcabo.pt) (Client Quit)
2022-12-07 20:58:00 +0100 <gurkenglas> I guess that'll come with the automated coder revolution one of these years, then
2022-12-07 20:58:25 +0100shapr(~user@68.54.166.125) (Remote host closed the connection)
2022-12-07 21:09:17 +0100jmdaemon(~jmdaemon@user/jmdaemon)
2022-12-07 21:11:33 +0100son0p(~ff@S0106f88b37df247a.vn.shawcable.net)
2022-12-07 21:12:20 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Ping timeout: 255 seconds)
2022-12-07 21:12:46 +0100trev(~trev@user/trev) (Remote host closed the connection)
2022-12-07 21:12:49 +0100 <monochrom> IOError got its isFooError predicates from Haskell 98 long long before we thought up the Control.Exception idea. Kind of "the ship has sailed" by then, too late to change.
2022-12-07 21:15:34 +0100tremon(~tremon@83-84-18-241.cable.dynamic.v4.ziggo.nl)
2022-12-07 21:16:50 +0100 <gurkenglas> In hls, when I mouseover "else" I get a type annotation. How do I get a type annotation for an arbitrary term I selected? Mousing over it gets me an annotation for whichever word I'm hovering over.
2022-12-07 21:17:19 +0100 <dminuoso> That depends on your editor and its lsp integration.
2022-12-07 21:17:31 +0100 <dminuoso> hls will respond to whatever the lsp client will ask it
2022-12-07 21:17:53 +0100 <dminuoso> though `else` is not a valid expression
2022-12-07 21:18:01 +0100 <dminuoso> So that's definitely a curious example
2022-12-07 21:18:14 +0100 <dminuoso> (Perhaps HLS has some kind of heuristic for this?)
2022-12-07 21:18:26 +0100 <gurkenglas> else was my example because it's not a valid expression so hls knows to give a type for the entire if-then-else block
2022-12-07 21:19:41 +0100 <monochrom> The most obvious thing to try is drag-selecting a subexpression.
2022-12-07 21:19:45 +0100 <dminuoso> Im guessing HLS will go up in the CST until it finds a full expression?
2022-12-07 21:20:17 +0100 <dminuoso> Which if you do what monochrom suggested wouldnt happen, since the selected region would already be an expression
2022-12-07 21:20:22 +0100 <monochrom> But if that doesn't do it, then it's also pretty obvious that either there is no way or there is a way but it's so obscure you won't want to know.
2022-12-07 21:20:36 +0100 <gurkenglas> tried drag-selecting. it's vscode
2022-12-07 21:21:37 +0100 <monochrom> I'm a defeatist and I enjoy the bliss of not using hls at all so I won't have to worry about expecting perfection and getting disappointed.
2022-12-07 21:22:28 +0100 <festive_kurbus> moom #haskell devolved into nihilism again
2022-12-07 21:22:49 +0100 <monochrom> A very humble emacs haskell-mode already does (with help from ghci integration) drag-select subexpr for type. dante does too.
2022-12-07 21:23:26 +0100 <dminuoso> "with help from ghci integration", the standard haskell-mode does not do that.
2022-12-07 21:23:33 +0100 <dminuoso> What are you using?
2022-12-07 21:23:52 +0100 <monochrom> OK, drag-select plus a hotkey, and the hotkey is not bound by default, I had to add one clause in my .emacs, but the feature exists.
2022-12-07 21:23:54 +0100 <gurkenglas> https://marketplace.visualstudio.com/items?itemName=haskell.haskell
2022-12-07 21:24:07 +0100 <monochrom> The standard haskell-mode. It does.
2022-12-07 21:24:56 +0100 <dminuoso> Oh it does?>
2022-12-07 21:25:40 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 252 seconds)
2022-12-07 21:25:45 +0100 <monochrom> ghci has a "what's the type of the thing from line x column y to line z column t" command. Unusable for humans but machine has no problem. haskell-mode has function/command haskell-mode-show-type-at to call up ghci's command. I bound it to a hotkey.
2022-12-07 21:26:32 +0100jmdaemon(~jmdaemon@user/jmdaemon) (Quit: ZNC 1.8.2 - https://znc.in)
2022-12-07 21:26:50 +0100 <monochrom> Very unknown feature because by the time ghci added it and haskell-mode and dante added it, everyone was already hyping about ghc-mod and HLS and etc
2022-12-07 21:27:03 +0100kenran(~user@user/kenran)
2022-12-07 21:27:23 +0100 <monochrom> So everyone simply inferred, from the hype, that there is no other way.
2022-12-07 21:27:57 +0100 <monochrom> or s/other/low-tech/
2022-12-07 21:28:14 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 21:28:16 +0100 <geekosaur> nobody wants low-tech ways
2022-12-07 21:28:17 +0100 <monochrom> This is how advertisements work psychologically in general.
2022-12-07 21:28:27 +0100dminuosowants physical buttons in his car
2022-12-07 21:28:39 +0100 <Rembane> +1
2022-12-07 21:29:29 +0100 <monochrom> A TV ad that says "with Benilyn your cold symptoms will be gone in 2 weeks" is truthful but mislead you to wrongly believe that without medication your cold symptoms would not be gone in 14 days.
2022-12-07 21:30:17 +0100 <Rembane> Withouth Benilyn they are gone in ten days!
2022-12-07 21:30:29 +0100 <gurkenglas> intero had it way before ghci, right?
2022-12-07 21:31:59 +0100 <monochrom> I also read that IRL there was a politician whose election platform was like "if you elect me, I'll make your foo tax rate to be bar percent!", bar being a pretty nice low number. The catch is that before the election the foo tax rate was already at bar percent.
2022-12-07 21:32:11 +0100seriously_guest(~seriously@2001:1c06:2715:c200:1a82:76d8:bd30:82fc)
2022-12-07 21:32:28 +0100money_(~money@user/polo)
2022-12-07 21:33:53 +0100 <EvanR> we all got a letter from the assessor sayings vote to limit the property tax increase to 10% this year. Elsewhere there was a report saying it would default to 2%
2022-12-07 21:34:05 +0100 <dolio> I don't think so. Wasn't intero using the same mechanism as dante, except it only worked with stack?
2022-12-07 21:35:07 +0100 <geekosaur> dante used ghci, intero involved a modified stack-only ghci iirc
2022-12-07 21:35:22 +0100 <monochrom> I heard people asking about why stack rebuilt intero repeatedly. I assume that it implies that intero uses GHC API like ghc-mod did.
2022-12-07 21:35:34 +0100 <monochrom> Oh modified ghci, haha that's epic.
2022-12-07 21:35:43 +0100 <monochrom> worst of both worlds haha
2022-12-07 21:35:56 +0100 <geekosaur> well, anything using ghc-api in a general fashion is just a reworked ghci
2022-12-07 21:36:09 +0100 <monochrom> OK fair.
2022-12-07 21:36:12 +0100 <geekosaur> I don't know exact details but ghci is a thin wrapper over ghc-api
2022-12-07 21:36:37 +0100 <geekosaur> (exact details re intero that os)
2022-12-07 21:36:39 +0100 <geekosaur> *is
2022-12-07 21:37:25 +0100 <gurkenglas> *looks at ListT* *looks at ListT done right* neither of these are what I want, I think O_o. I want IO [a]
2022-12-07 21:37:47 +0100 <monochrom> IO [a] would be the former ListT.
2022-12-07 21:37:49 +0100 <gurkenglas> am i... about to reach for acme-iot
2022-12-07 21:38:08 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 21:38:30 +0100 <monochrom> OK, unless the former ListT's >>= is not to your liking.
2022-12-07 21:38:55 +0100 <gurkenglas> oh, i failed to look at the former ListT instead of two different search results for the done right one
2022-12-07 21:39:21 +0100 <gurkenglas> and thought the difference between them must be some technicality i didnt see at first glance
2022-12-07 21:40:11 +0100kenran(~user@user/kenran) (Remote host closed the connection)
2022-12-07 21:40:14 +0100 <gurkenglas> the >>= logic should be... everything in line 118 happens before everything in line 119
2022-12-07 21:41:06 +0100 <seriously_guest> hey ... Im having some trouble understanding the motivation section of applicative functors in CIS 194... Why would we write a function (Name -> String -> Employee) -> (Maybe Name -> Maybe String -> Maybe Employee); when we could just have a (Maybe Name -> Maybe String -> Employee)
2022-12-07 21:41:29 +0100 <gurkenglas> (logic perhaps not being the right phrase, instead of "IO sequencing")
2022-12-07 21:42:01 +0100 <monochrom> I don't understand the question.
2022-12-07 21:42:25 +0100 <geekosaur> seriously_guest, what does your function produce if either Name or String is Nothing?
2022-12-07 21:42:57 +0100 <seriously_guest> geekosaur Employee (Nothing) (Nothing)
2022-12-07 21:43:12 +0100 <monochrom> Does Employee allow that?
2022-12-07 21:43:17 +0100 <seriously_guest> or Employee (Just "Frank") (Nothing)
2022-12-07 21:44:18 +0100 <seriously_guest> Employee by the examples defition does not monochrom
2022-12-07 21:44:29 +0100 <geekosaur> then you have the point
2022-12-07 21:44:51 +0100 <monochrom> I'm too lazy to search. Which URL has the definition of Employee?
2022-12-07 21:44:53 +0100 <seriously_guest> But thats why im suggeesting just create a data Employee = Employee (Maybe Name) (Maybe String)
2022-12-07 21:44:54 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 21:45:00 +0100 <seriously_guest> https://www.cis.upenn.edu/~cis1940/spring13/lectures/10-applicative.html
2022-12-07 21:45:15 +0100 <monochrom> Well then Employee doesn't allow Nothing.
2022-12-07 21:45:18 +0100 <dsal> Do you want an employee whose name you don't know?
2022-12-07 21:45:44 +0100 <dsal> An Employee Has No Name
2022-12-07 21:45:54 +0100 <monochrom> If one day you have a webapp in which "data Employee = Employee (Maybe Name) (Maybe String)" is totally legit, good for you.
2022-12-07 21:46:00 +0100 <seriously_guest> haha... no
2022-12-07 21:46:04 +0100 <geekosaur> right, what if your business logic doesn't allow anemployee without a name? do you have to drag around a Just that shouldn't ever be needed?
2022-12-07 21:46:07 +0100eggplantade(~Eggplanta@104-55-37-220.lightspeed.sntcca.sbcglobal.net) (Remote host closed the connection)
2022-12-07 21:46:11 +0100 <monochrom> For now, my webapp says that it should make no sense and it should be disallowed.
2022-12-07 21:46:38 +0100 <monochrom> Then I really legit only have either Just (Employee foo bar) or Nothing, i.e., Maybe Employee.
2022-12-07 21:46:42 +0100 <dsal> It's a good idea to make illegal states unrepresentable.
2022-12-07 21:46:58 +0100 <dminuoso> Now whether a missing name is illegal state, that's for you to decide.
2022-12-07 21:47:11 +0100 <seriously_guest> I see
2022-12-07 21:47:45 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 21:48:29 +0100huskle(~huskle@250.79-105-213.static.virginmediabusiness.co.uk)
2022-12-07 21:48:39 +0100 <huskle> hi, i just installed haskell on ubuntu
2022-12-07 21:48:45 +0100 <huskle> having just installed ubuntu
2022-12-07 21:48:52 +0100 <huskle> when i do cabal v2-install random
2022-12-07 21:48:54 +0100 <huskle> it fails!
2022-12-07 21:49:15 +0100Inoperable(~PLAYER_1@fancydata.science) (Ping timeout: 268 seconds)
2022-12-07 21:49:18 +0100 <Rembane> huskle: How does it fail?
2022-12-07 21:49:21 +0100 <huskle> i installed ghcup using curl as it says to
2022-12-07 21:49:34 +0100 <huskle> Rembrane: /usr/bin/ld.gold: error: cannot find -lgmp
2022-12-07 21:50:08 +0100 <huskle> is this a dependency that ghcup should have installed?
2022-12-07 21:50:20 +0100 <dolio> You probably need to install it with apt.
2022-12-07 21:50:20 +0100 <Rembane> huskle: Have you tried sudo apt-get install build-essential
2022-12-07 21:50:24 +0100 <monochrom> sudo apt install libgmp-dev
2022-12-07 21:50:38 +0100 <monochrom> build-essential doesn't have it.
2022-12-07 21:50:59 +0100 <geekosaur> but you'll probably need build-essential anyway
2022-12-07 21:51:07 +0100 <huskle> Rembrane: says they are there already
2022-12-07 21:51:09 +0100 <monochrom> Yeah, build-essential is for gcc.
2022-12-07 21:51:49 +0100ft(~ft@p508dbd59.dip0.t-ipconnect.de)
2022-12-07 21:51:57 +0100 <huskle> yay! now it works
2022-12-07 21:52:13 +0100 <huskle> libgmp-dev seems to have been missing
2022-12-07 21:52:24 +0100 <huskle> so why does ghcup not install this?
2022-12-07 21:52:57 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 268 seconds)
2022-12-07 21:53:04 +0100 <monochrom> ghcup does not know that it is not "pacman foobar libgmp-dev"?
2022-12-07 21:53:25 +0100 <mauke> I don't think you need the -dev package; libgmp10 might have been sufficient
2022-12-07 21:53:30 +0100 <dolio> Yeah, does ghcup interact at all with the system package manager?
2022-12-07 21:53:35 +0100 <monochrom> Alternatively but equivalently, "patches welcome".
2022-12-07 21:53:57 +0100 <monochrom> Although, ghcup absolutely avoids sudo.
2022-12-07 21:54:10 +0100 <huskle> beyond me
2022-12-07 21:54:17 +0100 <monochrom> libgmp10 is positively verified to be insufficient.
2022-12-07 21:54:26 +0100 <mauke> oh, neat
2022-12-07 21:54:50 +0100 <huskle> sounds like an issue encountered before!
2022-12-07 21:54:54 +0100waleee(~waleee@2001:9b0:213:7200:cc36:a556:b1e8:b340)
2022-12-07 21:55:38 +0100 <huskle> im making some differentialble random number sequences if anyones interested
2022-12-07 21:55:49 +0100 <huskle> its for machine learning
2022-12-07 21:55:56 +0100haritz(~hrtz@user/haritz) (Quit: ZNC 1.8.2+deb2 - https://znc.in)
2022-12-07 21:56:13 +0100 <monochrom> An ubuntu libfoo-dev package contains *.h files and a symlink from libfoo.so to libfoo.so.x.y.z. libfoo.so.x.y.z being already in the libfoo package.
2022-12-07 21:56:31 +0100 <monochrom> GHC just needs the libfoo.so symlink.
2022-12-07 21:56:49 +0100 <monochrom> You could argue that you don't need libfoo-dev for that, you could make the symlink yourself.
2022-12-07 21:57:12 +0100 <huskle> (!?)
2022-12-07 21:57:14 +0100 <monochrom> Explaining that takes 100 times more effort than instructing "sudo apt install libfoo-dev".
2022-12-07 21:57:19 +0100 <mauke> that strikes me as slightly weird. why is the .so link part of the dev package?
2022-12-07 21:57:35 +0100 <monochrom> Ideology?
2022-12-07 21:57:54 +0100 <monochrom> Every linux distro makes ideological, irrational decisions.
2022-12-07 21:58:02 +0100 <monochrom> Just look at archlinux. :)
2022-12-07 21:58:22 +0100 <mauke> I'm not sure "irrational" has semantics
2022-12-07 21:58:32 +0100 <huskle> well, better than windows installing updates that ensure the bloatawre cannot be disabled
2022-12-07 21:59:05 +0100 <huskle> that also use so much resources as to prevent taskmanager from being opened to stop other processes
2022-12-07 21:59:34 +0100 <monochrom> Oh speaking of bloatware on Windows. I learned yesterday that Chinese bloatware installers are like "In the following don't deselect the packages you don't want".
2022-12-07 21:59:38 +0100 <huskle> i want the last year of my life back
2022-12-07 22:00:35 +0100 <huskle> anyway, with linux, i can now open a text editor and a directory browser in less than a minute!
2022-12-07 22:00:45 +0100 <EvanR> yes irrational = not rational is terribly negative. What's the positive version
2022-12-07 22:00:49 +0100 <monochrom> For the semantics of "irrational", you can start with your own "slightly weird, why did they do it?"
2022-12-07 22:00:50 +0100 <huskle> i used to use wordpad, because it took *less* time than eclipseIDE to start
2022-12-07 22:01:23 +0100 <seriously_guest> Can someone help me write an implementation of this type (continuing my previoius train of thought): (Name -> String -> Employee) ->
2022-12-07 22:01:23 +0100 <seriously_guest> (Maybe Name -> Maybe String -> Maybe Employee)
2022-12-07 22:01:43 +0100 <mauke> \_ _ _ -> Nothing
2022-12-07 22:01:48 +0100 <huskle> lol
2022-12-07 22:02:07 +0100 <monochrom> You can do pattern matching on two Maybe parameters.
2022-12-07 22:02:08 +0100 <huskle> can they have no name or string or do they have to have a name or a string?
2022-12-07 22:02:31 +0100 <seriously_guest> Have to have a name and a string
2022-12-07 22:02:34 +0100 <monochrom> You can first call it 4 cases. Later you can merge 3 of them.
2022-12-07 22:02:50 +0100 <huskle> not name *and* ...
2022-12-07 22:03:00 +0100 <mauke> @djinn (Name -> String -> Employee) -> (Maybe Name -> Maybe String -> Maybe Employee)
2022-12-07 22:03:00 +0100 <lambdabot> Error: Undefined type Name
2022-12-07 22:03:06 +0100 <dolio> EvanR: Has a continued fraction representation with specified, finite gaps between non-zero coefficients.
2022-12-07 22:03:25 +0100 <huskle> so its more like (Maybe (Name,String)) -> Maybe Employee?
2022-12-07 22:03:30 +0100 <huskle> because then you can use fmap
2022-12-07 22:03:44 +0100 <huskle> % :t fmap @Maybe
2022-12-07 22:03:44 +0100 <yahb2> fmap @Maybe :: (a -> b) -> Maybe a -> Maybe b
2022-12-07 22:03:52 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 22:03:55 +0100 <seriously_guest> Sorry huskle I believe you joined after I explained that this is in regards to cis 194 assignment 10
2022-12-07 22:04:09 +0100 <monochrom> No, totally unlike (Maybe (Name,String)) -> Maybe Employee
2022-12-07 22:04:10 +0100 <huskle> ok
2022-12-07 22:04:15 +0100 <mauke> @djinn (name -> string -> employee) -> (Maybe name -> Maybe string -> Maybe employee)
2022-12-07 22:04:15 +0100 <lambdabot> f a b c =
2022-12-07 22:04:15 +0100 <lambdabot> case b of
2022-12-07 22:04:15 +0100 <lambdabot> Nothing -> Nothing
2022-12-07 22:04:15 +0100 <lambdabot> Just d -> case c of
2022-12-07 22:04:15 +0100 <lambdabot> Nothing -> Nothing
2022-12-07 22:04:17 +0100 <lambdabot> Just e -> Just (a d e)
2022-12-07 22:04:36 +0100 <mauke> well, that's not very elegant
2022-12-07 22:06:07 +0100 <seriously_guest> What would the types of a, b, and c be ?
2022-12-07 22:06:07 +0100festive_kurbus(~festive_k@user/kurbus) (Quit: Client closed)
2022-12-07 22:06:16 +0100 <mauke> wtf
2022-12-07 22:06:31 +0100 <mauke> it's your type signature
2022-12-07 22:06:57 +0100 <mauke> I gave it to the bot; it generated code; why are you now asking for the type of the code we started from?
2022-12-07 22:07:19 +0100 <seriously_guest> why are you even assuming i know what this bot is doing?
2022-12-07 22:08:15 +0100 <monochrom> Why is no one caring about my advice?
2022-12-07 22:08:16 +0100 <mauke> hmm
2022-12-07 22:08:48 +0100 <mauke> it's not so much that; what I'm assuming is that you can read/understand basic haskell code
2022-12-07 22:08:53 +0100 <iqubic> Just use liftA3
2022-12-07 22:09:17 +0100 <dsal> liftA2
2022-12-07 22:09:26 +0100 <iqubic> Oh yeah
2022-12-07 22:09:38 +0100 <seriously_guest> im learning haskell... let me write out my question in a more understandable format for you. If you have a function f with the type (Name -> String -> Employee) -> (Maybe Name -> Maybe String -> Maybe Employee), if you write a funcion definition using the pattern matching structure of f a b c = ...; what is the type of a, b, and c?
2022-12-07 22:09:44 +0100 <dsal> Off by one lift
2022-12-07 22:09:52 +0100 <gurkenglas> What's the current way to make hls add imports for me?
2022-12-07 22:09:57 +0100 <mauke> seriously_guest: ooh, you're stuck on currying!
2022-12-07 22:10:32 +0100 <mauke> seriously_guest: f a b c = ... is syntactic sugar for f = \a -> \b -> \c -> ...
2022-12-07 22:10:35 +0100 <huskle> seriously_guest: thats wrong
2022-12-07 22:10:35 +0100 <kjlid[m]> I just ate a curry
2022-12-07 22:10:44 +0100 <huskle> you have one function argument
2022-12-07 22:10:45 +0100 <mauke> seriously_guest: and the type A -> B -> C means A -> (B -> C)
2022-12-07 22:10:55 +0100 <mauke> huskle: dude, what
2022-12-07 22:11:13 +0100 <huskle> f g =
2022-12-07 22:11:21 +0100 <mauke> huskle: did you not read what the bot wrote?
2022-12-07 22:11:23 +0100 <mauke> also, you're wrong
2022-12-07 22:11:29 +0100 <huskle> chill!
2022-12-07 22:11:37 +0100 <huskle> this bot has you all het up
2022-12-07 22:11:45 +0100 <huskle> its a beginer q
2022-12-07 22:12:06 +0100 <huskle> and your all like "all function arrows are monomorphisms"
2022-12-07 22:12:20 +0100 <EvanR> f g =, the type of g is (Name -> String -> Employee)
2022-12-07 22:12:22 +0100 <mauke> seriously_guest: well, that assumes you know what \a -> ... means. do you?
2022-12-07 22:12:31 +0100 <mauke> if not, this explanation was useless :-)
2022-12-07 22:12:39 +0100 <huskle> EvanR: thanks...
2022-12-07 22:13:23 +0100 <seriously_guest> EvanR how about f g h
2022-12-07 22:13:30 +0100 <huskle> functions in one argument* (i have no idea what a monomorphism is. sry!)
2022-12-07 22:13:41 +0100 <EvanR> h sounds like you want a second function argument?
2022-12-07 22:13:51 +0100 <EvanR> your next argument would be Maybe Name if you want to do it that way
2022-12-07 22:14:29 +0100 <EvanR> f g mname mstring =
2022-12-07 22:14:31 +0100 <huskle> % :t curry
2022-12-07 22:14:31 +0100 <yahb2> curry :: ((a, b) -> c) -> a -> b -> c
2022-12-07 22:14:41 +0100 <huskle> % :t fmap @Maybe . uncurry
2022-12-07 22:14:41 +0100 <yahb2> fmap @Maybe . uncurry ; :: (a -> b1 -> b2) -> Maybe (a, b1) -> Maybe b2
2022-12-07 22:14:57 +0100 <huskle> your sure its not this?
2022-12-07 22:15:09 +0100 <huskle> he said they have to have a name *and* a string
2022-12-07 22:15:22 +0100 <huskle> they*
2022-12-07 22:15:32 +0100 <EvanR> sounds like you need Applicative but also we can't get there yet
2022-12-07 22:15:48 +0100Inoperable(~PLAYER_1@fancydata.science)
2022-12-07 22:15:55 +0100 <EvanR> you have to swim before you can crawl
2022-12-07 22:16:14 +0100 <mauke> seriously_guest: but to answer your question in full, a :: (Name -> String -> Employee); b :: Maybe Name; c :: Maybe String
2022-12-07 22:17:25 +0100pavonia(~user@user/siracusa)
2022-12-07 22:18:17 +0100 <gurkenglas> Is there a MonadIO-lifted version of https://hackage.haskell.org/package/text-2.0.1/docs/Data-Text-IO.html ?
2022-12-07 22:18:19 +0100tvandinther(~tvandinth@111.69.34.210)
2022-12-07 22:18:27 +0100 <seriously_guest> I apologize for causing any confusion... let me take a step back and give everyone some context. Im reading week 10 of Yorgeys CIS 194 2013. Im struggling to get through the MOTIVATION section of the reading. I don't see how having a function of type (Name -> String -> Employee) -> (Maybe Name -> Maybe String -> Maybe Employee) is useful. IM NOT
2022-12-07 22:18:28 +0100 <seriously_guest> SAYING ITS NOT USEFUL. Im only saying that I CANT UNDERSTAND WHY its useful. I understand that in a business use case, we want a way to be able to parse employee io data into an Employee data type. I don understand how that function does this.
2022-12-07 22:18:32 +0100 <dminuoso> gurkenglas: Probably not. You can just liftIO
2022-12-07 22:19:03 +0100 <dminuoso> seriously_guest: We could perhaps start with a different motivation.
2022-12-07 22:19:10 +0100 <geekosaur> gurkenglas, I would expect one of the alternative Preludes to have it
2022-12-07 22:19:16 +0100 <dminuoso> seriously_guest: Say you have two numbers held in a variable `a` and `b`, and you want to add them.
2022-12-07 22:19:28 +0100 <dminuoso> seriously_guest: This would just be `a + b`, right?
2022-12-07 22:19:35 +0100 <seriously_guest> right
2022-12-07 22:20:00 +0100 <dminuoso> So in that `a :: Int` and `b :: Int`
2022-12-07 22:20:13 +0100 <gurkenglas> maybe there's some Data.Coercible-like hackery that you can wrap around a code block that is correct except for some missing liftIOs to pepper them in
2022-12-07 22:20:18 +0100 <huskle> idk, maybe so its like "well if either of these records are left blank, then we can propegate an error in the form of Nothing
2022-12-07 22:20:33 +0100 <dminuoso> % let a = 1; b = 2; in a + b
2022-12-07 22:20:33 +0100 <yahb2> 3
2022-12-07 22:20:43 +0100 <geekosaur> seriously_guest, you start out with an ordinary constructor for an Employee, and Applicative gives you a conditional one that gives you an Employee only if the Name and String are valid (not Nothing). this is then useful with business logic that validates those and produces Just them or Nothing if they're not valid
2022-12-07 22:20:50 +0100kenaryn(~aurele@cre71-h03-89-88-44-27.dsl.sta.abo.bbox.fr)
2022-12-07 22:20:59 +0100 <geekosaur> (there is for example a validation package that helps with that part)
2022-12-07 22:21:12 +0100 <dminuoso> So for some reason however, assume that `a` and `b` might be empty however (say we read them from a file, but perhaps the file is empty), so we use `Maybe Int` to represent them instead. So we have `ma :: Maybe Int` and `mb :: Maybe Int`
2022-12-07 22:21:16 +0100 <geekosaur> so now you can compose parts together to build your busines slogic from pieces
2022-12-07 22:21:27 +0100 <dminuoso> seriously_guest: Do you see, how you can no longer just (+) them together?
2022-12-07 22:21:53 +0100 <dminuoso> % let ma = Just 3; mb = Nothing in ma + mb
2022-12-07 22:21:53 +0100 <yahb2> <interactive>:86:1: error: ; • No instance for (Num (Maybe Integer)) arising from a use of ‘it’ ; • In the first argument of ‘Yahb2Defs.limitedPrint’, namely ‘it’ ; In a stmt of an in...
2022-12-07 22:22:11 +0100irrgit__(~irrgit@176.113.74.74)
2022-12-07 22:22:23 +0100 <seriously_guest> dminuoso yup because there no longer Int, an instance of Number. They are now Maybe Int
2022-12-07 22:22:27 +0100 <dminuoso> Right.
2022-12-07 22:22:35 +0100 <huskle> dminuoso: i like your example better because it is more clear that it has to have both entries or its an error
2022-12-07 22:22:46 +0100 <dminuoso> But we may want to still express the idea of "if both numbers are present, add them together"
2022-12-07 22:22:47 +0100 <gurkenglas> yahb2: that should say "expected Int but found Maybe Int"
2022-12-07 22:22:48 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 260 seconds)
2022-12-07 22:22:53 +0100 <dminuoso> gurkenglas: nope.
2022-12-07 22:23:04 +0100 <dminuoso> The error is quite right
2022-12-07 22:23:08 +0100 <huskle> :t maybe
2022-12-07 22:23:09 +0100 <lambdabot> b -> (a -> b) -> Maybe a -> b
2022-12-07 22:23:35 +0100 <dminuoso> seriously_guest: So what we can write then is:
2022-12-07 22:23:38 +0100 <gurkenglas> dminuoso: Do you mean, I misdiagnosed his issue, or you disapprove of my proposal? :D
2022-12-07 22:23:47 +0100 <dminuoso> Both.
2022-12-07 22:23:55 +0100 <huskle> :t both
2022-12-07 22:23:56 +0100 <lambdabot> (Data.Bitraversable.Bitraversable r, Applicative f) => (a -> f b) -> r a a -> f (r b b)
2022-12-07 22:24:00 +0100 <huskle> !?
2022-12-07 22:24:01 +0100 <dminuoso> % let ma = Just 3; mb = Just 4 in liftA2 (+) ma mb -- seriously_guest
2022-12-07 22:24:01 +0100 <yahb2> <interactive>:88:33: error: ; Variable not in scope: ; liftA2 :: (a0 -> a0 -> a0) -> Maybe a1 -> Maybe a2 -> t
2022-12-07 22:24:07 +0100 <dminuoso> % import Control.Applicative (liftA2)
2022-12-07 22:24:07 +0100 <yahb2> <no output>
2022-12-07 22:24:09 +0100 <dminuoso> % let ma = Just 3; mb = Just 4 in liftA2 (+) ma mb -- seriously_guest
2022-12-07 22:24:09 +0100 <yahb2> Just 7
2022-12-07 22:24:15 +0100 <dsal> :t each
2022-12-07 22:24:16 +0100 <lambdabot> (Each s t a b, Applicative f) => (a -> f b) -> s -> f t
2022-12-07 22:24:18 +0100 <dminuoso> % :t liftA2
2022-12-07 22:24:18 +0100 <yahb2> liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
2022-12-07 22:24:24 +0100 <dminuoso> seriously_guest: ^- is this clear?
2022-12-07 22:24:38 +0100 <huskle> % :t liftA2 (+)
2022-12-07 22:24:38 +0100 <yahb2> liftA2 (+) :: (Applicative f, Num c) => f c -> f c -> f c
2022-12-07 22:24:43 +0100 <dminuoso> (It may not be immediately necessary to understand *why* liftA2 works, but merely what it does)
2022-12-07 22:24:52 +0100 <gurkenglas> dminuoso: ohh! :D i thought yahb2 was a user barely scrounging together the willpower to paste what ghci spat out to us so we can debug his unrelated error
2022-12-07 22:24:53 +0100 <huskle> % liftA2 (+) Nothing (Just 4)
2022-12-07 22:24:53 +0100 <yahb2> Nothing
2022-12-07 22:25:00 +0100 <huskle> % liftA2 (+) (Just 3) (Just 4)
2022-12-07 22:25:00 +0100 <yahb2> Just 7
2022-12-07 22:25:04 +0100 <huskle> yay!
2022-12-07 22:25:13 +0100takuan(~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection)
2022-12-07 22:25:14 +0100irrgit_(~irrgit@176.113.74.74) (Ping timeout: 246 seconds)
2022-12-07 22:25:31 +0100 <mauke> % instance (Num a) => Num (Maybe a) where { (+) = liftA2 (+); (*) = liftA2 (*); abs = fmap abs; signum = fmap signum; fromInteger = pure . fromInteger; negate = fmap negate }
2022-12-07 22:25:32 +0100 <yahb2> <no output>
2022-12-07 22:25:37 +0100 <seriously_guest> dminuoso "% let ma = Just 3; mb = Just 4 in liftA2 (+) ma mb" - Its clear as in Yes theres a function lifaA2 which runs the function (+) inside the Functor m's values
2022-12-07 22:25:37 +0100 <mauke> > Just 3 + Just 4
2022-12-07 22:25:39 +0100 <lambdabot> error:
2022-12-07 22:25:39 +0100 <lambdabot> • No instance for (Num (Maybe Integer))
2022-12-07 22:25:39 +0100 <lambdabot> arising from a use of ‘e_134’
2022-12-07 22:25:42 +0100 <mauke> % Just 3 + Just 4
2022-12-07 22:25:42 +0100 <yahb2> Just 7
2022-12-07 22:25:51 +0100 <huskle> !?
2022-12-07 22:25:56 +0100 <mauke> % Just 3 + Nothing
2022-12-07 22:25:56 +0100 <yahb2> Nothing
2022-12-07 22:26:04 +0100 <huskle> Just Int has a Num instance?
2022-12-07 22:26:09 +0100 <mauke> it does now
2022-12-07 22:26:13 +0100 <dminuoso> seriously_guest: Yup! So in some sense liftA2 is similar to fmap, except for functions with an arity of 2, whereas fmap only works for functions with arity of 1.
2022-12-07 22:26:19 +0100 <dminuoso> seriously_guest: Is this clear so far?
2022-12-07 22:26:54 +0100 <huskle> % :t negate @(Just Int)
2022-12-07 22:26:54 +0100 <yahb2> <interactive>:1:10: error: ; Not in scope: type constructor or class ‘Just’ ; A data constructor of that name is in scope; did you mean DataKinds?
2022-12-07 22:27:01 +0100 <huskle> % :t negate @(Maybe Int)
2022-12-07 22:27:01 +0100 <yahb2> negate @(Maybe Int) :: Maybe Int -> Maybe Int
2022-12-07 22:27:25 +0100 <huskle> did you just make this in another window in a convo with yahb?
2022-12-07 22:27:31 +0100 <mauke> huskle: no
2022-12-07 22:27:33 +0100gmg(~user@user/gehmehgeh)
2022-12-07 22:27:39 +0100 <dminuoso> In truth Applicative comes with (<*>), which lets us generalize this liftA2 for functions of _arbitrary_ arity. So say you have a function taking 5 values, but you have 5 Maybe wrapped things instead, then Applicative will let you deal with it exactly like shown above with liftA2.
2022-12-07 22:27:39 +0100 <huskle> ...
2022-12-07 22:27:44 +0100 <mauke> I made it in this window, literally two lines before
2022-12-07 22:27:49 +0100 <seriously_guest> Yeah clear so far! to levelset though, I want to ensure were on the quest to explaining why (a -> b -> c) -> (f a -> f b -> f c) is useful in our example
2022-12-07 22:28:01 +0100 <dminuoso> seriously_guest: Sure! I just wanted to set the scene.
2022-12-07 22:28:07 +0100 <seriously_guest> cool
2022-12-07 22:28:21 +0100 <huskle> oh the lamdabot error confused me
2022-12-07 22:28:28 +0100 <dminuoso> 22:27:39 dminuoso | In truth Applicative comes with (<*>), which lets us generalize this liftA2 for functions of _arbitrary_ arity. So say you have a function taking 5 values, but you have 5 Maybe wrapped things instead, then Applicative will let you deal with it exactly like shown above with liftA2.
2022-12-07 22:28:33 +0100 <dsal> @src liftA2
2022-12-07 22:28:33 +0100 <lambdabot> liftA2 f a b = f <$> a <*> b
2022-12-07 22:28:56 +0100 <mauke> huskle: note how the instance body is generic and could be reused for any Applicative
2022-12-07 22:29:00 +0100 <dminuoso> seriously_guest: So if you have a function that demand exactly 5 values of some particular types, but if some of them are missing, you clearly cant produce a sensible result with that.
2022-12-07 22:29:15 +0100 <mauke> (including IO)
2022-12-07 22:29:36 +0100 <huskle> some subset of functors?
2022-12-07 22:30:04 +0100 <dminuoso> seriously_guest: The *lifting* is just a means to an end here.
2022-12-07 22:30:20 +0100 <huskle> hey, does anyone want to see my differentiable random sequences thing?
2022-12-07 22:30:30 +0100 <dminuoso> seriously_guest: It's not per-se being able to do `(a -> b -> c) -> (f a -> f b -> f c)`, but rather doing this *and then* applying it to `f a` and `f b`
2022-12-07 22:30:54 +0100 <dminuoso> seriously_guest: So its really about `I have A -> B -> C, but am given `Maybe A` and `Maybe `B`, the above will let me get a `Maybe C` back.
2022-12-07 22:31:16 +0100 <dminuoso> (Note Im particularly monomorphizing `f` to `Maybe` here.
2022-12-07 22:31:32 +0100biberu(~biberu@user/biberu) (Read error: Connection reset by peer)
2022-12-07 22:31:43 +0100 <huskle> https://paste.tomsmeding.com/rZsfvbud
2022-12-07 22:31:47 +0100 <dminuoso> Quite similarly to how `liftA2 (+)` is useful for being able to do `liftA2 (+) ma mb`
2022-12-07 22:32:19 +0100 <dminuoso> Of course in code style it can be useful to decouple them, so you maybe do let `add_maybes = liftA2 (+) in ...`
2022-12-07 22:32:24 +0100 <huskle> see, it works!
2022-12-07 22:33:01 +0100wootehfoot(~wootehfoo@user/wootehfoot) (Read error: Connection reset by peer)
2022-12-07 22:33:07 +0100 <dsal> > let (+?) = liftA2 (+) in Just 3 +? Just 5
2022-12-07 22:33:08 +0100 <lambdabot> Just 8
2022-12-07 22:33:16 +0100 <huskle> the guest is not interested
2022-12-07 22:33:19 +0100 <seriously_guest> dminuoso im still comprehending some things... just a sec
2022-12-07 22:34:00 +0100 <huskle> let us know when you are done comprehending things
2022-12-07 22:35:35 +0100gmg(~user@user/gehmehgeh) (Ping timeout: 255 seconds)
2022-12-07 22:35:35 +0100stiell(~stiell@gateway/tor-sasl/stiell) (Ping timeout: 255 seconds)
2022-12-07 22:36:15 +0100biberu(~biberu@user/biberu)
2022-12-07 22:36:26 +0100gmg(~user@user/gehmehgeh)
2022-12-07 22:36:45 +0100stiell(~stiell@gateway/tor-sasl/stiell)
2022-12-07 22:38:56 +0100 <seriously_guest> dminuoso Im clear on this bit "  dminuoso | In truth Applicative comes with (<*>)"..... (<*>) lets us lift functors and apply a function of the values. It does this as long as the number of arguments and the number of Maybes (functors) are the same
2022-12-07 22:39:10 +0100 <seriously_guest> I think im clear on this bit*
2022-12-07 22:39:20 +0100 <seriously_guest> on the values*
2022-12-07 22:39:22 +0100money_(~money@user/polo) (Quit: money_)
2022-12-07 22:39:27 +0100 <dsal> Consider ($) vs. (<$>) vs. (<*>)
2022-12-07 22:39:37 +0100Unicorn_Princess(~Unicorn_P@user/Unicorn-Princess/x-3540542) (Quit: Leaving)
2022-12-07 22:39:43 +0100 <dminuoso> seriously_guest: A slight correcftion:
2022-12-07 22:40:06 +0100 <dminuoso> If you want to use the generalizsed version, its <$> and <*> for most simple use cases.
2022-12-07 22:40:07 +0100 <huskle> ... we can write liftN, for any N, sure
2022-12-07 22:40:22 +0100 <dminuoso> While <*> on its own is useful too, the usecase we are talking about always looks like
2022-12-07 22:40:31 +0100 <dminuoso> f <$> a1 <*> a2 <*> a3 ... <*> an
2022-12-07 22:40:40 +0100 <dsal> > let (+?+) = (fmap . fmap) show . liftA2 (+) `on` readMaybe in "2" +?+ "5" -- Look, I've invented tcl!
2022-12-07 22:40:41 +0100 <lambdabot> Just "7"
2022-12-07 22:40:59 +0100 <huskle> yuk
2022-12-07 22:41:27 +0100 <dminuoso> seriously_guest: So `<$>` on its own lets you do this for functions taking just one argument, and `<*>` lets you extend that (together with <$>) for functions of arbitrary arity.
2022-12-07 22:41:28 +0100 <huskle> % @src liftA3
2022-12-07 22:41:28 +0100 <yahb2> <interactive>:120:1: error: parse error on input ‘@’
2022-12-07 22:41:37 +0100 <huskle> % :src liftA3
2022-12-07 22:41:37 +0100 <yahb2> unknown command ':src' ; use :? for help.
2022-12-07 22:41:40 +0100 <huskle> ?
2022-12-07 22:41:40 +0100jakalx(~jakalx@base.jakalx.net) (Error from remote client)
2022-12-07 22:41:43 +0100 <dsal> @src liftA3
2022-12-07 22:41:43 +0100 <lambdabot> Source not found.
2022-12-07 22:41:58 +0100 <huskle> oh right its a lambdabot thing
2022-12-07 22:42:04 +0100 <seriously_guest> dminuoso Gotcha there... now im trying to understand this part "It's not per-se being able to do `(a -> b - ......"
2022-12-07 22:42:08 +0100 <dsal> Imagine it said liftA3 f a b c = f <$> a <*> b <*> c
2022-12-07 22:42:17 +0100 <dminuoso> seriously_guest: If you have got what you just said, dont worry about it.
2022-12-07 22:42:26 +0100 <huskle> > let liftA3 f a b c = f <$> a <*> b <*> c
2022-12-07 22:42:27 +0100 <lambdabot> <no location info>: error:
2022-12-07 22:42:27 +0100 <lambdabot> not an expression: ‘let liftA3 f a b c = f <$> a <*> b <*> c’
2022-12-07 22:42:31 +0100 <dminuoso> seriously_guest: liftA2 (or liftA3) is just a convenience for the 2-arity (or 3-arity) function case above.
2022-12-07 22:42:34 +0100 <huskle> sorry
2022-12-07 22:42:44 +0100Topsi1(~Topsi@dyndsl-095-033-143-231.ewe-ip-backbone.de) (Ping timeout: 256 seconds)
2022-12-07 22:42:50 +0100Topsi(~Topsi@dyndsl-095-033-227-140.ewe-ip-backbone.de)
2022-12-07 22:42:51 +0100 <dsal> huskle: lambdabot doesn't know all the things, it just has some representative sources that make things easier to understand.
2022-12-07 22:42:59 +0100 <dminuoso> seriously_guest: So instead of writing `f <$> a1 <*> a2 <*> a3` you can also write `liftA3 f a1 a2 a3` which does exactly the same thing.
2022-12-07 22:42:59 +0100 <huskle> ahh
2022-12-07 22:43:08 +0100 <dsal> e.g., this is definitely not sum:
2022-12-07 22:43:10 +0100 <dsal> @src sum
2022-12-07 22:43:10 +0100 <lambdabot> sum = foldl (+) 0
2022-12-07 22:43:16 +0100jakalx(~jakalx@base.jakalx.net)
2022-12-07 22:43:20 +0100 <huskle> ok
2022-12-07 22:43:26 +0100 <c_wraith> @src foldr
2022-12-07 22:43:26 +0100 <lambdabot> foldr f z [] = z
2022-12-07 22:43:26 +0100 <lambdabot> foldr f z (x:xs) = f x (foldr f z xs)
2022-12-07 22:43:29 +0100 <huskle> just some totally random reference!
2022-12-07 22:43:36 +0100 <dsal> sum in Foldable is `sum = getSum #. foldMap' Sum`
2022-12-07 22:43:37 +0100 <c_wraith> that one's even further from how GHC does it...
2022-12-07 22:43:38 +0100 <dminuoso> seriously_guest: So what Im saying here is that `liftA3` is not useful because it lets you do this crazy transformation, but rather that `liftA3` lets you apply a 3-arity function to three Maybe things.
2022-12-07 22:43:59 +0100 <dminuoso> (And the crazy transformation is just in order to apply it to three Maybe things)
2022-12-07 22:44:02 +0100 <huskle> was looking at the source for "randoms"
2022-12-07 22:44:06 +0100 <huskle> uses build
2022-12-07 22:44:09 +0100 <huskle> for fusion
2022-12-07 22:44:11 +0100 <huskle> pretty cool
2022-12-07 22:44:14 +0100 <seriously_guest> So liftA3 (\x -> x + 1) (Maybe 1) (Maybe 2) (Maybe 3) = (Maybe 2) (Maybe 3) (Maybe 4)
2022-12-07 22:44:24 +0100 <huskle> https://hackage.haskell.org/package/random-1.2.1.1/docs/src/System.Random.html#randoms
2022-12-07 22:44:30 +0100 <dminuoso> seriously_guest: No thats not how it works.
2022-12-07 22:44:35 +0100 <dminuoso> seriously_guest: Imagine this:
2022-12-07 22:44:43 +0100 <dminuoso> % fun = \x y z -> (x + y) * z
2022-12-07 22:44:43 +0100 <yahb2> <no output>
2022-12-07 22:44:51 +0100 <dminuoso> % fun x y z = (x + y) * z
2022-12-07 22:44:51 +0100 <yahb2> <no output>
2022-12-07 22:45:22 +0100 <dminuoso> % fun :: Int -> Int -> Int -> Int; fun x y z = (x + y) * z
2022-12-07 22:45:22 +0100 <yahb2> <no output>
2022-12-07 22:45:38 +0100 <dminuoso> Now imagine you want to apply `fun` to three `Maybe Int` instead.
2022-12-07 22:45:47 +0100 <dsal> % :t liftA3 fun
2022-12-07 22:45:47 +0100 <yahb2> <interactive>:1:1: error: ; • Variable not in scope: liftA3 :: (Int -> Int -> Int -> Int) -> t ; • Perhaps you meant ‘liftA2’ (imported from Control.Applicative)
2022-12-07 22:45:50 +0100 <huskle> % liftA3 (\x y z -> x + y * z) (Just 2) (Just 3) (Just 5)
2022-12-07 22:45:50 +0100 <yahb2> <interactive>:132:1: error: ; • Variable not in scope: ; liftA3 ; :: (a0 -> a0 -> a0 -> a0) -> Maybe a1 -> Maybe a2 -> Maybe a3 -> t ; • Perhaps you meant ‘liftA2’ (import...
2022-12-07 22:45:52 +0100 <dminuoso> Then you can just either write `liftA3 fun a1 a2 a3` or `fun <$> a1 <*> a2 <*> a3`
2022-12-07 22:46:07 +0100 <dminuoso> % import Control.Applicative (liftA3)
2022-12-07 22:46:08 +0100 <yahb2> <no output>
2022-12-07 22:46:12 +0100 <dminuoso> % liftA3 (\x y z -> x + y * z) (Just 2) (Just 3) (Just 5)
2022-12-07 22:46:12 +0100 <yahb2> Just 17
2022-12-07 22:46:21 +0100 <dsal> % :t liftA3 fun
2022-12-07 22:46:21 +0100 <yahb2> liftA3 fun :: Applicative f => f Int -> f Int -> f Int -> f Int
2022-12-07 22:46:26 +0100 <dminuoso> % liftA3 (\x y z -> x + y * z) <$> Just 2 <*> Just 3 <*> Just 5
2022-12-07 22:46:26 +0100 <yahb2> <interactive>:142:1: error: ; • Ambiguous type variable ‘f0’ arising from a use of ‘Yahb2Defs.limitedPrint’ ; prevents the constraint ‘(Show (f0 Integer))’ from being solved. ; Prob...
2022-12-07 22:46:36 +0100eggplantade(~Eggplanta@104-55-37-220.lightspeed.sntcca.sbcglobal.net)
2022-12-07 22:46:38 +0100 <dminuoso> % liftA3 fun <$> Just 2 <*> Just 3 <*> Just 5
2022-12-07 22:46:38 +0100 <yahb2> Oops, something went wrong
2022-12-07 22:46:41 +0100 <dminuoso> Wow.
2022-12-07 22:46:44 +0100dminuosopokes tomsmeding
2022-12-07 22:46:47 +0100 <huskle> why you still have the things between
2022-12-07 22:46:50 +0100 <huskle> % liftA3 (\x y z -> x + y * z) (Just 2) (Just 3) (Just 5)
2022-12-07 22:46:50 +0100 <yahb2> <interactive>:4:1: error: ; Variable not in scope: ; liftA3 ; :: (a0 -> a0 -> a0 -> a0) -> Maybe a1 -> Maybe a2 -> Maybe a3 -> t
2022-12-07 22:46:51 +0100 <dminuoso> % fun <$> Just 2 <*> Just 3 <*> Just 5
2022-12-07 22:46:51 +0100 <yahb2> <interactive>:6:1: error: ; Variable not in scope: fun :: a0 -> a1 -> a2 -> b
2022-12-07 22:47:04 +0100 <dminuoso> % fun :: Int -> Int -> Int -> Int; fun x y z = (x + y) * z
2022-12-07 22:47:04 +0100 <yahb2> <no output>
2022-12-07 22:47:09 +0100 <dminuoso> % fun <$> Just 2 <*> Just 3 <*> Just 5
2022-12-07 22:47:09 +0100 <yahb2> Just 25
2022-12-07 22:47:16 +0100Topsi(~Topsi@dyndsl-095-033-227-140.ewe-ip-backbone.de) (Ping timeout: 256 seconds)
2022-12-07 22:47:27 +0100 <huskle> % liftA3 fun (Just 2) (Just 3) (Just 5)
2022-12-07 22:47:27 +0100 <yahb2> <interactive>:12:1: error: ; Variable not in scope: ; liftA3 ; :: (Int -> Int -> Int -> Int) ; -> Maybe a0 -> Maybe a1 -> Maybe a2 -> t
2022-12-07 22:47:30 +0100 <huskle> rrg!!
2022-12-07 22:47:41 +0100 <huskle> % liftA3 f a b c = f <$> a <*> b <*> c
2022-12-07 22:47:41 +0100 <yahb2> <no output>
2022-12-07 22:47:42 +0100 <dminuoso> seriously_guest: Are you still with me?
2022-12-07 22:47:45 +0100 <huskle> % liftA3 fun (Just 2) (Just 3) (Just 5)
2022-12-07 22:47:45 +0100 <yahb2> Just 25
2022-12-07 22:47:48 +0100 <huskle> yay!
2022-12-07 22:48:06 +0100 <seriously_guest> Ohhh right ... so arity of x means a function taking x parameters ... Sorry yes!
2022-12-07 22:48:11 +0100 <dminuoso> Yup.
2022-12-07 22:48:38 +0100 <dminuoso> seriously_guest: One useful bit, that relates to this, is that in reality functions only take one argument in Haskell
2022-12-07 22:48:54 +0100 <dminuoso> It is not an absolute truth and only perspective
2022-12-07 22:49:14 +0100 <huskle> % :t fun <$> Just 1 <*> Just 2
2022-12-07 22:49:14 +0100 <yahb2> fun <$> Just 1 <*> Just 2 :: Maybe (Int -> Int)
2022-12-07 22:49:17 +0100 <dminuoso> Something like `f :: Int -> Int -> Int` actually has implicit parenthesis `f :: Int -> (Int -> Int)`
2022-12-07 22:49:20 +0100 <huskle> % :t fun <$> Just 1
2022-12-07 22:49:20 +0100 <yahb2> fun <$> Just 1 :: Maybe (Int -> Int -> Int)
2022-12-07 22:49:32 +0100Inoperable(~PLAYER_1@fancydata.science) (Ping timeout: 256 seconds)
2022-12-07 22:49:37 +0100 <huskle> % :t (fun <$>)
2022-12-07 22:49:37 +0100 <yahb2> (fun <$>) :: Functor f => f Int -> f (Int -> Int -> Int)
2022-12-07 22:49:41 +0100 <dminuoso> equivalently applying to two functions sort of happens one argument at a time `f 1 2` is actually the same as `(f 1) 2`
2022-12-07 22:49:45 +0100 <dminuoso> seriously_guest: Does this make sense as well?
2022-12-07 22:49:55 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net)
2022-12-07 22:50:40 +0100 <dminuoso> But for sake of disussion, when we talk about a function like `Int -> Int -> Int` we usually adopt the notion that this has "2 parameters", knowing that in reality it is a function that returns a function (which is an equivalent encoding)
2022-12-07 22:50:52 +0100 <dminuoso> So its useful to be able to shift this perspective from time to time
2022-12-07 22:51:11 +0100 <dminuoso> This has some useful consequences (and again this relates to the confusion that sparked me getting into the discussion)
2022-12-07 22:51:32 +0100eggplantade(~Eggplanta@104-55-37-220.lightspeed.sntcca.sbcglobal.net) (Ping timeout: 268 seconds)
2022-12-07 22:51:41 +0100 <seriously_guest> It makes sense as much as it can for me... I dont think its necesarily clicked on the importance of such a notion tho.
2022-12-07 22:52:04 +0100 <dminuoso> If you have a function `f :: Int -> String -> Bool`, then applying `f` to a single argument produces the rest of that function
2022-12-07 22:52:11 +0100 <dminuoso> So `f 10` has the type `String -> Bool`
2022-12-07 22:52:18 +0100 <dminuoso> And `f 10 "Foo"` has type Bool
2022-12-07 22:52:33 +0100 <dminuoso> seriously_guest | Yeah clear so far! to levelset though, I want to ensure were on the quest to explaining why (a -> b -> c) -> (f a -> f b -> f c) is useful in our example
2022-12-07 22:52:38 +0100Topsi(~Topsi@dyndsl-095-033-039-218.ewe-ip-backbone.de)
2022-12-07 22:52:41 +0100 <dminuoso> So if we look at:
2022-12-07 22:52:46 +0100 <dminuoso> liftA3 fun 1 2 3
2022-12-07 22:52:51 +0100 <dminuoso> (((liftA3 fun) 1) 2) 3
2022-12-07 22:53:32 +0100 <dsal> % liftA3 fun (Just 2) (Just 3) <$> [Just 1, Just 3, Just 5]
2022-12-07 22:53:32 +0100 <yahb2> [Just 5,Just 15,Just 25]
2022-12-07 22:53:34 +0100 <dminuoso> See how we could see this as first `liftA3 fun` turning `Int -> Int -> Int -> Int` into `Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int`
2022-12-07 22:53:43 +0100 <dminuoso> Err
2022-12-07 22:54:01 +0100 <dminuoso> liftA3 fun (Just 1) (Just 2) (Just 3)
2022-12-07 22:54:07 +0100beteigeuze(~Thunderbi@a79-169-109-107.cpe.netcabo.pt)
2022-12-07 22:54:11 +0100 <dminuoso> (((liftA3 fun) (Just 1)) (Just 2)) (Just 3)
2022-12-07 22:54:14 +0100eggplantade(~Eggplanta@104-55-37-220.lightspeed.sntcca.sbcglobal.net)
2022-12-07 22:54:39 +0100 <dminuoso> So after that lifting, we then apply the resulting function `Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int` to `Just 1`, producing a function of type `Maybe Int -> Maybe Int -> Maybe Int` and so forth.
2022-12-07 22:55:01 +0100 <dminuoso> seriously_guest: Do you see why Im saying that focusing on what `liftA2` or `liftA3` do by themselves is not that useful?
2022-12-07 22:55:02 +0100son0p(~ff@S0106f88b37df247a.vn.shawcable.net) (Ping timeout: 246 seconds)
2022-12-07 22:55:04 +0100 <huskle> so how do i use applicative to do this?
2022-12-07 22:55:05 +0100 <huskle> https://paste.tomsmeding.com/3SrqURCW
2022-12-07 22:55:11 +0100euandreh(~Thunderbi@179.214.113.107)
2022-12-07 22:55:18 +0100 <dsal> % iterate (liftA3 fun (Just 2) (Just 3)) (Just 1)
2022-12-07 22:55:18 +0100 <yahb2> [Just 1,Just 5,Just 25,Just 125,Just 625,Just 3125,Just 15625,Just 78125,Just 390625,Just 1953125,Just 9765625,Just 48828125,Just 244140625,Just 1220703125,Just 6103515625,Just 30517578125,Just 152...
2022-12-07 22:55:25 +0100 <huskle> see how the things in the list of list are functions?
2022-12-07 22:55:37 +0100 <huskle> i want to apply them to a list of list of input arguments
2022-12-07 22:56:12 +0100 <dminuoso> huskle: its your lucky day
2022-12-07 22:56:20 +0100 <dminuoso> (Applicative f, Applicative g) => Applicative (Compose f g)
2022-12-07 22:56:34 +0100 <dminuoso> The composition of two applicatives is an applicative too.
2022-12-07 22:56:41 +0100 <huskle> using coerce?
2022-12-07 22:56:53 +0100 <dminuoso> You can use coerce to get into Compose sure
2022-12-07 22:57:03 +0100 <dminuoso> Or just manually wrap and unwrap
2022-12-07 22:57:14 +0100 <dminuoso> Similarly your fmap can be avoided as well
2022-12-07 22:57:26 +0100 <dminuoso> (that double fmap I mean)
2022-12-07 22:57:26 +0100 <huskle> > [[+1]] <*> [[1]]
2022-12-07 22:57:27 +0100 <lambdabot> error:
2022-12-07 22:57:27 +0100 <lambdabot> A section must be enclosed in parentheses thus: (+ 1)
2022-12-07 22:57:28 +0100codaraxis(~codaraxis@user/codaraxis)
2022-12-07 22:57:37 +0100 <huskle> > [[(+1)]] <*> [[1]]
2022-12-07 22:57:39 +0100 <lambdabot> error:
2022-12-07 22:57:39 +0100 <lambdabot> • Couldn't match expected type ‘[a1] -> b’
2022-12-07 22:57:39 +0100 <lambdabot> with actual type ‘[a0 -> a0]’
2022-12-07 22:57:40 +0100 <dsal> > [succ, pred] <*> [1..5]
2022-12-07 22:57:42 +0100 <lambdabot> [2,3,4,5,6,0,1,2,3,4]
2022-12-07 22:58:10 +0100 <huskle> where does the coerce go?
2022-12-07 22:58:13 +0100 <dminuoso> % import Data.Functor.Compose
2022-12-07 22:58:13 +0100 <yahb2> <no output>
2022-12-07 22:59:25 +0100 <huskle> heres the smooth noise module again; https://paste.tomsmeding.com/zKMllsZH
2022-12-07 22:59:29 +0100 <dminuoso> % import Data.Functor.Compose
2022-12-07 22:59:29 +0100 <yahb2> <no output>
2022-12-07 22:59:33 +0100 <dminuoso> % (Compose [[succ], [pred]]) <*> (Compose [[1..5], [2..3]])
2022-12-07 22:59:34 +0100euandreh(~Thunderbi@179.214.113.107) (Remote host closed the connection)
2022-12-07 22:59:35 +0100 <dminuoso> % (Compose [[succ], [pred]]) <*> (Compose [[1..5], [2..3]])
2022-12-07 22:59:35 +0100 <yahb2> Compose [[2,3,4,5,6],[3,4],[0,1,2,3,4],[1,2]]
2022-12-07 22:59:55 +0100euandreh(~Thunderbi@179.214.113.107)
2022-12-07 22:59:57 +0100 <dminuoso> I would probably just write myself an ap2 rather
2022-12-07 23:00:02 +0100euandreh(~Thunderbi@179.214.113.107) (Client Quit)
2022-12-07 23:00:03 +0100 <dminuoso> Seems more sane
2022-12-07 23:00:12 +0100 <huskle> ok, so i just wrap the list of lists in compose and then unwrap
2022-12-07 23:00:13 +0100 <seriously_guest> Alright here we go... So LiftA3 (\x y z -> x + y + z) (f Int) (f Int) (f Int) converts   (Int -> Int -> Int) -> (f Int -> f Int -> f Int)
2022-12-07 23:00:26 +0100kenaryn(~aurele@cre71-h03-89-88-44-27.dsl.sta.abo.bbox.fr) (Quit: leaving)
2022-12-07 23:00:38 +0100zq(~zq@xorshift.org) ()
2022-12-07 23:00:43 +0100 <dminuoso> % ap2 f a = getCompose (Compose f `ap` Compose a)
2022-12-07 23:00:43 +0100 <yahb2> <interactive>:14:33: error: ; • Variable not in scope: ; ap :: Compose f g a -> Compose f1 g1 a1 -> Compose f2 g2 a2 ; • Perhaps you meant one of these: ; ‘a’ (line 14), ‘ma...
2022-12-07 23:00:49 +0100 <dminuoso> % import Control.Applicative
2022-12-07 23:00:49 +0100 <yahb2> <no output>
2022-12-07 23:01:01 +0100 <dminuoso> seriously_guest: For sake of clarity, pick a particular `f`
2022-12-07 23:01:05 +0100 <dminuoso> seriously_guest: Lets pin it to `Maybe`
2022-12-07 23:01:29 +0100 <dminuoso> There's a many reasons why thinking just about particular type is more helpful at the beginning
2022-12-07 23:01:37 +0100 <dsal> seriously_guest: Also, off-by-one lift :)
2022-12-07 23:01:49 +0100 <dminuoso> % ap2 f a = getCompose (Compose f `ap` Compose a)
2022-12-07 23:01:49 +0100 <yahb2> <interactive>:18:33: error: ; • Variable not in scope: ; ap :: Compose f g a -> Compose f1 g1 a1 -> Compose f2 g2 a2 ; • Perhaps you meant one of these: ; ‘a’ (line 18), ‘ma...
2022-12-07 23:02:01 +0100 <dminuoso> Oh its monad isnt it
2022-12-07 23:02:07 +0100 <dminuoso> % ap2 f a = getCompose (Compose f <*> Compose a)
2022-12-07 23:02:07 +0100 <yahb2> <no output>
2022-12-07 23:02:24 +0100 <dminuoso> % [[succ], [pred]] `ap2` [[1..5], [2..3]]
2022-12-07 23:02:24 +0100 <yahb2> [[2,3,4,5,6],[3,4],[0,1,2,3,4],[1,2]]
2022-12-07 23:02:33 +0100 <dsal> "ap" being a monad seems like a silly wart.
2022-12-07 23:02:37 +0100 <dminuoso> huskle: this is what I would do (well I would actually use #. in there as well)
2022-12-07 23:02:47 +0100 <dminuoso> dsal: historical reasons, its from before applicative was a thing
2022-12-07 23:02:50 +0100dsalisn't good at wording right now
2022-12-07 23:03:36 +0100 <dminuoso> % import Data.Coerce
2022-12-07 23:03:36 +0100 <yahb2> <no output>
2022-12-07 23:03:42 +0100 <dminuoso> % :set -XMagicHash
2022-12-07 23:03:42 +0100 <yahb2> <no output>
2022-12-07 23:04:18 +0100 <dminuoso> % (#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c); (#.) = coerce
2022-12-07 23:04:18 +0100 <yahb2> <interactive>:28:67: error: ; • Couldn't match representation of type ‘c’ with that of ‘a -> c’ ; arising from a use of ‘coerce’ ; ‘c’ is a rigid type variable bound by ; ...
2022-12-07 23:04:26 +0100 <dminuoso> % (#.) :: Coercible b c => (b -> c) -> (a -> b) -> (a -> c); (#.) _f = coerce
2022-12-07 23:04:26 +0100 <yahb2> <no output>
2022-12-07 23:04:38 +0100 <dminuoso> % ap2 f a = getCompose #. (Compose f <*> Compose a)
2022-12-07 23:04:38 +0100 <yahb2> <interactive>:32:26: error: ; • Couldn't match expected type: a1 -> Compose f1 g1 a2 ; with actual type: Compose f g b ; • Possible cause: ‘(<*>)’ is applied to too many a...
2022-12-07 23:04:46 +0100 <huskle> sorry that last paste had an error
2022-12-07 23:04:47 +0100 <huskle> https://paste.tomsmeding.com/jqWTKDzk
2022-12-07 23:06:00 +0100 <seriously_guest> So LiftA3,  when given a function that operates on three values of type a, applied to 3 functors of type Maybe a, converts the given function (a -> a -> a -> a) into (Maybe a -> Maybe a -> Maybe a -> Maybe a)...
2022-12-07 23:06:35 +0100 <seriously_guest> I'm definetly way better off then where I started lol
2022-12-07 23:07:19 +0100 <dminuoso> seriously_guest: Mmm there falseties in that statement.
2022-12-07 23:07:33 +0100 <huskle> https://paste.tomsmeding.com/wTdCxUik
2022-12-07 23:07:33 +0100 <dminuoso> liftA3 will by itself do that conversion
2022-12-07 23:07:42 +0100 <huskle> that has the version not using the magic hash
2022-12-07 23:08:01 +0100 <dminuoso> I gotta do some pondering why my #. isnt working here
2022-12-07 23:08:58 +0100 <seriously_guest> Ok so maybe let me step back and see how such a conversion can take place with actual code. For example again, lets define the function fn :: (Name -> String -> Employee) -> (Maybe Name -> Maybe String -> Maybe Employee)
2022-12-07 23:09:16 +0100 <dminuoso> seriously_guest: Yes indeed! That sounds like a good excercise.
2022-12-07 23:09:50 +0100 <huskle> whats it for anyway this  #.
2022-12-07 23:10:23 +0100 <huskle> % fn = liftA2
2022-12-07 23:10:24 +0100 <yahb2> <no output>
2022-12-07 23:10:43 +0100 <huskle> % fn = liftA2 @Maybe
2022-12-07 23:10:43 +0100 <yahb2> <no output>
2022-12-07 23:10:50 +0100 <huskle> % :t fn
2022-12-07 23:10:50 +0100 <yahb2> fn :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
2022-12-07 23:11:15 +0100 <dminuoso> Ohh hold on, I see what's wrong.
2022-12-07 23:11:27 +0100 <huskle> seriously_guest: its ok?
2022-12-07 23:11:31 +0100 <dminuoso> I think its bedtime given that I thought (#.) was even needed.
2022-12-07 23:11:47 +0100 <huskle> dont worry
2022-12-07 23:11:49 +0100 <dminuoso> huskle: Its essentially a coercing (.) that ignores the left argument
2022-12-07 23:11:57 +0100 <dminuoso> Here's an example of where its useful
2022-12-07 23:12:01 +0100 <huskle> ok
2022-12-07 23:12:03 +0100 <dminuoso> sum = getSum #. foldMap' Sum
2022-12-07 23:12:26 +0100 <dminuoso> If we used (.) we could arise with some performance problems
2022-12-07 23:12:40 +0100 <seriously_guest> fn g = maybeEmployee
2022-12-07 23:12:55 +0100 <seriously_guest> sorry... didnt mean to hit enter
2022-12-07 23:13:03 +0100 <dminuoso> No worries
2022-12-07 23:14:24 +0100 <dminuoso> huskle: its mainly just useful in situations where you have eta reduced code and want to trip through newtypes
2022-12-07 23:14:52 +0100 <huskle> eta reduction!? sounds fully jargon
2022-12-07 23:15:14 +0100 <dminuoso> sum = getSum #. foldMap' Sum
2022-12-07 23:15:16 +0100 <dminuoso> as opposed to
2022-12-07 23:15:22 +0100 <dminuoso> sum xs = getSum (foldMap' Sum xs)
2022-12-07 23:15:44 +0100 <dminuoso> Note that the obvious `sum = getSum . foldMap' Sum` can have performance issues
2022-12-07 23:16:31 +0100 <dminuoso> tps://gitlab.haskell.org/ghc/ghc/-/issues/7542
2022-12-07 23:16:37 +0100 <seriously_guest> fn g = maybeEmployee where maybeEmployee (Nothing) (Nothing) = Nothing; maybeEmployee (Just _) (Nothing) = Nothing; maybeEmployee (Nothing) (Just _) = Nothing; maybeEmployee (Just name) (Just phone) = Maybe (Employee name phone)
2022-12-07 23:17:30 +0100 <seriously_guest> ugh i didnt even apply g anywhere... im gonna go to bed myself
2022-12-07 23:17:32 +0100 <dminuoso> Indeed, that looks correct. Note, that the parenthesis around nullary constructors like Nothing are not needed and should be omitted.
2022-12-07 23:17:40 +0100 <dminuoso> Ah heh yeah
2022-12-07 23:17:47 +0100 <dminuoso> Well you used `Employee` instead of `g`
2022-12-07 23:18:06 +0100 <seriously_guest> :O
2022-12-07 23:18:12 +0100 <dminuoso> But beyond that, its right.
2022-12-07 23:18:30 +0100 <dminuoso> seriously_guest: note that for writing this out, there's a much much easier way
2022-12-07 23:18:32 +0100 <dminuoso> and scalable way
2022-12-07 23:18:38 +0100 <seriously_guest> Where do I donate haha...  ive abused this room long enough
2022-12-07 23:18:50 +0100 <EvanR> right here, over here
2022-12-07 23:18:51 +0100 <dminuoso> (Also note that the data constructor is called Just, not Maybe)
2022-12-07 23:19:11 +0100 <dminuoso> `maybeEmployee g (Just name) (Just phone) = Just (g name phone); maybeEmployee _ _ _ = Nothing`
2022-12-07 23:19:14 +0100 <huskle> I WILL TAKE DONATIONS!!
2022-12-07 23:19:27 +0100 <dminuoso> This style scales nicer, since it wont require me to elaborate all the combinations
2022-12-07 23:19:30 +0100 <iqubic> huskle: For what?
2022-12-07 23:19:34 +0100 <huskle> lol
2022-12-07 23:19:37 +0100 <huskle> to not die
2022-12-07 23:19:50 +0100 <EvanR> imagine if you will that Just and Nothing are color coded blue for value and Maybe is colored red for types
2022-12-07 23:19:53 +0100 <EvanR> or something
2022-12-07 23:20:09 +0100 <EvanR> this guy conor mcbride uses a lot of colors to keep it straight
2022-12-07 23:20:23 +0100 <dminuoso> seriously_guest: And of course, we can just write this every time we need it. But we can more easily get the same by just writing `liftA2 g`, and have it work for an arbitrary g, or equivalently just write `g <$> maybeName <*> maybePhone`
2022-12-07 23:21:45 +0100merijn(~merijn@86-86-29-250.fixed.kpn.net) (Ping timeout: 268 seconds)
2022-12-07 23:23:10 +0100 <seriously_guest> Gotcha... Id really like to see this logic from end to end; applied to the use case of possibly having null/empty data ... Not knowing how you can wrap possiblt null/empty values from an IO call inside a maybe, in haskell, is just making my brain skip
2022-12-07 23:24:31 +0100 <dminuoso> seriously_guest: THat's part of why Im telling you to focus on just a particular type, like Maybe.
2022-12-07 23:24:35 +0100 <dminuoso> Take small steps.
2022-12-07 23:25:18 +0100 <dminuoso> Part of what makes Applicative special is that it generalized over these types in a lawful manner. But it is difficult to fully see and understand the pattern if you havent experimented and worked with individual instances.
2022-12-07 23:25:53 +0100 <tvandinther> Design question: When would you justify making a typeclass over making the same functions pattern match a sum type?
2022-12-07 23:26:10 +0100 <dminuoso> tvandinther: Probably never.
2022-12-07 23:26:20 +0100 <huskle> how do you mean?
2022-12-07 23:26:23 +0100 <huskle> classes rule
2022-12-07 23:26:52 +0100 <dminuoso> I think a lot of typeclasses are ill-placed and not a good idea.
2022-12-07 23:26:58 +0100troydm(~troydm@host-176-37-124-197.b025.la.net.ua)
2022-12-07 23:27:23 +0100 <seriously_guest> Yes i see, thank you... If I could maybe just write a quick service that calls some external function(api) which returns a employee as JSON... { "name": "jay", phone: null } and work with that
2022-12-07 23:27:59 +0100 <dminuoso> seriously_guest: Sure, though that kind of interaction will require a combination of several libraries involving a variety of more complex ideas.
2022-12-07 23:28:10 +0100 <dminuoso> So it may not be the best of ideas
2022-12-07 23:28:25 +0100 <tvandinther> So say I had a few data structures which I want to prettyPrint, it would be advised to just make a single `prettyPrint` function that pattern matched the constructors of the various data structures? vs. creating a new `PrettyPrint a` typeclass that needs to implement `prettyPrint`
2022-12-07 23:28:29 +0100 <dminuoso> HTTP interaction is not particularly pleasent, our libraries do not take shortcuts,.
2022-12-07 23:28:47 +0100 <dminuoso> tvandinther: pretty printing is exactly the kind of thing typeclasses are absolutely poor at.
2022-12-07 23:28:53 +0100 <seriously_guest> I know ): I've been on this journey for half a year now; started with the goal of writing the backends for my app in haskell... this is where im at currently
2022-12-07 23:28:58 +0100 <dminuoso> I would just write `pprFoo`, `pprBar`, `pprQuux` functions as needed.
2022-12-07 23:29:25 +0100 <dminuoso> The only value you get from a typeclass is remembering only a single name, but with ctags or HLS something like completion will address that for you
2022-12-07 23:29:30 +0100 <seriously_guest> But off to bed now... thanks for everyones help...
2022-12-07 23:29:35 +0100 <dminuoso> The price is that you cant have two pretty printing for the same type
2022-12-07 23:29:45 +0100 <dminuoso> seriously_guest: Good night and good luck on your journey!
2022-12-07 23:29:56 +0100 <seriously_guest> :)
2022-12-07 23:30:02 +0100seriously_guest(~seriously@2001:1c06:2715:c200:1a82:76d8:bd30:82fc) (Quit: Client closed)
2022-12-07 23:30:18 +0100 <dminuoso> tvandinther: And further, you cant parameterize them (unless you start making even more typeclasses), you cant embed any information as to what it does
2022-12-07 23:30:40 +0100 <dminuoso> and it introduces more brittleness since if the type switches, it may still end up pretty printing *something* (but quite possibly not what you intended)
2022-12-07 23:30:52 +0100 <tvandinther> thats a good point
2022-12-07 23:31:18 +0100 <tvandinther> you said never earlier, but is there really any condition in which a custom typeclass would be justified?
2022-12-07 23:31:46 +0100 <tvandinther> Seems like its probably a tool reserved for libraries
2022-12-07 23:31:53 +0100 <dminuoso> https://stackoverflow.com/a/74380240/6636995 is an answer of mine that goes into the subject in amore detailed manner
2022-12-07 23:32:01 +0100 <dminuoso> it depends on who you ask
2022-12-07 23:32:14 +0100 <dminuoso> but there is a certain consensus that typeclasses are best used for things that are lawful
2022-12-07 23:32:23 +0100 <dminuoso> Such that you can infer laws from the typeclass usage itself
2022-12-07 23:33:03 +0100 <tvandinther> and I presume laws don't change on a whim
2022-12-07 23:33:19 +0100 <tvandinther> making the brittleness less of an issue
2022-12-07 23:33:26 +0100 <dminuoso> Say if you have `a >> b >> c`, then you can associate it as `(a >> b) >> c` or `a >> (b >> c)` - and you can infer this from just seeing >> and knowing monad laws.
2022-12-07 23:34:06 +0100 <huskle> hey! i finished my smooth noise thing and it works!!
2022-12-07 23:34:24 +0100 <huskle> https://paste.tomsmeding.com/5h9Zleox
2022-12-07 23:34:30 +0100 <dminuoso> tvandinther: Right.
2022-12-07 23:34:30 +0100tromp(~textual@92-110-219-57.cable.dynamic.v4.ziggo.nl) (Quit: My iMac has gone to sleep. ZZZzzz…)
2022-12-07 23:34:43 +0100 <dminuoso> tvandinther: my rule of thumb is that typeclasses are very rarely the right tool.
2022-12-07 23:34:55 +0100 <dminuoso> Outside of situations where you're leveraging the type system
2022-12-07 23:35:26 +0100 <dminuoso> Sometimes there's no immediate way around it like in Generic code (but I recently adopted the notion that you're probably better using TH for most of these anyway)
2022-12-07 23:35:37 +0100 <huskle> erm, well actually it doesnt seem to work, those are supposed to be unifolrmly distributed on the unit interval
2022-12-07 23:35:49 +0100 <huskle> but they are smooth wrt to changes in the params!
2022-12-07 23:35:54 +0100Topsi(~Topsi@dyndsl-095-033-039-218.ewe-ip-backbone.de) (Read error: Connection reset by peer)
2022-12-07 23:36:01 +0100 <huskle> rrg..
2022-12-07 23:36:13 +0100 <huskle> see what i mean?
2022-12-07 23:36:17 +0100 <dminuoso> tvandinther: and further, typeclasses are almost assuredly the worst thing for parsing/serializing/deserializing/decoding/encoding/pretty printing
2022-12-07 23:36:25 +0100 <dminuoso> for the reasons outlined in my stackoverflow answer (and what I said earlier)
2022-12-07 23:36:50 +0100 <tvandinther> Cool, good to know. It didn't feel like the right tool but good to understand some of the reasons beyond feeling haha
2022-12-07 23:37:06 +0100 <tvandinther> Thanks
2022-12-07 23:37:15 +0100 <dminuoso> wel "the worst thing" is a bit of a hyperbole.
2022-12-07 23:37:24 +0100 <huskle> i think it must be averaging them or something...
2022-12-07 23:37:38 +0100 <huskle> and some are negative?
2022-12-07 23:37:45 +0100 <dminuoso> tvandinther: One thing where I do like typeclasses is classy lenses actually
2022-12-07 23:37:47 +0100king_gs(~Thunderbi@187.201.204.122)
2022-12-07 23:37:49 +0100 <huskle> Why Are Some Negative!?
2022-12-07 23:37:54 +0100 <EvanR> Yeah clearly you want to pretty print with Generics
2022-12-07 23:38:21 +0100 <huskle> oh the seeds are negative..
2022-12-07 23:39:10 +0100 <huskle> nope that doesnt get it
2022-12-07 23:39:21 +0100 <dminuoso> tvandinther: but this wildly depends on the usage scenario. In our SDN compiler, we we have over a dozen different notions of "network interface", but all of them have some CommonInterface, so its *very* useful to just express `f % commonInterface` without figuring out the exact types in the way when I just want that common structure they all share.
2022-12-07 23:39:34 +0100 <dminuoso> That's driven by a HasCommonInterface typeclass
2022-12-07 23:40:04 +0100 <dminuoso> (But here, the typeclass is directly tied to what is being produced, so there's no confusion ever
2022-12-07 23:40:16 +0100 <tvandinther> EvanR: What would generics add to the pretty printing?
2022-12-07 23:40:30 +0100 <EvanR> I'm half serious
2022-12-07 23:40:38 +0100 <EvanR> since generics is accessed via type classes
2022-12-07 23:40:55 +0100 <EvanR> but it does let you implement a pretty printer for all types at once
2022-12-07 23:41:02 +0100 <dminuoso> tvandinther: better indentation. :p
2022-12-07 23:41:16 +0100 <dminuoso> pretty-show/pretty-simple are amongst my staple libraries I add during debugging.
2022-12-07 23:41:35 +0100 <tvandinther> Oh yes, I've seen the "Has" pattern of typeclassing with optparse-applicative. Seems like a nice way to do fluent construction of data of mildly different shapes.
2022-12-07 23:41:39 +0100festive_kurbus(~festive_k@user/kurbus)
2022-12-07 23:41:42 +0100 <dminuoso> But then again, I dont want to add Generic just for the ability of nicer printing
2022-12-07 23:42:13 +0100 <dminuoso> My recent experiences with Generics have proven that its really terrible. :(
2022-12-07 23:42:57 +0100 <dminuoso> Had that one module with 33 data types, all deriving Generic, and using deriving-aeson to produce FromJSON and ToJSON instances. Simplifier ended up with 2 million types, compilation of that module with -O2 took about 4-5 minutes.
2022-12-07 23:43:01 +0100 <tvandinther> I used a generic recently to "annotate" a type with additional data, is that a good use-case?
2022-12-07 23:43:07 +0100 <dminuoso> Switched to TH equivalent code, and it went down to seconds..
2022-12-07 23:43:23 +0100 <dminuoso> tvandinther: Can you elaborate?
2022-12-07 23:44:52 +0100 <tvandinther> I'm starting to doubt whether I am referring to the correct thing. I'm under the assumption that generic refers to a type like `data Wrapper a = Wrapper {...`
2022-12-07 23:45:19 +0100 <tvandinther> But that's just my understanding of generics in an OOP context
2022-12-07 23:45:40 +0100 <dminuoso> No, Generics is a meta programming technique
2022-12-07 23:45:57 +0100 <dminuoso> As a random example:
2022-12-07 23:46:56 +0100 <dminuoso> You can just slap `deriving Generic` onto an arbtirary data type Foo, then write `instance FromJSON Foo; instance ToJSON Bar` and by magic hands, you have two instances that can serialize and deserialize your data type from and into some JSON format
2022-12-07 23:47:42 +0100 <dminuoso> So one can write up code that will behave depending on the type, in particular you can steer it based on things like constructor names, their types, etc..
2022-12-07 23:48:18 +0100 <tvandinther> How would that differ from `deriving (FromJSON, ToJSON)`
2022-12-07 23:48:26 +0100 <dminuoso> It wouldnt
2022-12-07 23:48:42 +0100 <tvandinther> same thing, different syntax?
2022-12-07 23:48:50 +0100 <dminuoso> tvandinther: that mechanism is the same except it uses the DeriveAnyClass extension
2022-12-07 23:49:01 +0100 <dminuoso> (it ends up doing the same)
2022-12-07 23:49:25 +0100 <tvandinther> except that you can derive an instance in a different module from the type declaration?
2022-12-07 23:49:29 +0100 <dminuoso> tvandinther: well the thing is
2022-12-07 23:49:30 +0100huskle(~huskle@250.79-105-213.static.virginmediabusiness.co.uk) (Ping timeout: 268 seconds)
2022-12-07 23:49:35 +0100 <dminuoso> Ah hold on
2022-12-07 23:49:42 +0100 <dminuoso> Slight misconfusion
2022-12-07 23:49:45 +0100 <dminuoso> │23:48:18 tvandinther | How would that differ from `deriving (FromJSON, ToJS
2022-12-07 23:49:48 +0100 <dminuoso> In principle this wont work
2022-12-07 23:49:56 +0100 <dminuoso> Because GHC doesnt know how to derive FromJSON
2022-12-07 23:50:25 +0100 <dminuoso> (With DeriveAnyClass you *can* write it, but then it amounts to just writing `instance FromJSON Foo`
2022-12-07 23:50:37 +0100 <dminuoso> Note that you will not specify an implementation
2022-12-07 23:50:44 +0100 <dminuoso> this works because FromJSON has a default implementation:
2022-12-07 23:50:53 +0100 <dminuoso> default parseJSON :: (Generic a, GFromJSON Zero (Rep a)) => Value -> Parser a
2022-12-07 23:50:58 +0100Tuplanolla(~Tuplanoll@91-159-68-152.elisa-laajakaista.fi) (Quit: Leaving.)
2022-12-07 23:51:02 +0100 <tvandinther> So they are the same provided you enable the language extension
2022-12-07 23:51:20 +0100 <dminuoso> So as long as the type has `Generic`, then using the magic GFromJSON typeclass an implementation can be conjured.
2022-12-07 23:51:40 +0100 <dminuoso> Which, beyond all the reasons I talked about earlier, has additional problems
2022-12-07 23:52:24 +0100 <dminuoso> Because the way GFromJSON works, is that Generics produces very deeply nested complicated types that directly reflect the data structure of the type itself. One way to think of typeclasses and instances, is that they provide a type-level `case-of`
2022-12-07 23:52:24 +0100 <tvandinther> And it can do this because there is an implementation for this typeclass for all base types, so generic derivations are algebraically constructed from those?
2022-12-07 23:52:34 +0100 <dminuoso> So with typeclasses you can scrutinize types sort of..
2022-12-07 23:52:39 +0100 <dminuoso> Its not very direct
2022-12-07 23:52:42 +0100 <dminuoso> Its not very fast either
2022-12-07 23:53:10 +0100 <dminuoso> tvandinther: Well GHC knows how to derive Generic (assuming DeriveGeneric is enabled)
2022-12-07 23:53:26 +0100 <dminuoso> Which is a typeclass that consists of two methods:
2022-12-07 23:53:30 +0100 <dminuoso> And an associated type
2022-12-07 23:53:45 +0100 <tvandinther> This sounds similar to Reflection in C#
2022-12-07 23:53:49 +0100 <dminuoso> It very much is
2022-12-07 23:53:52 +0100 <dminuoso> But it happens at compile time
2022-12-07 23:53:56 +0100 <dminuoso> Via typeclasses and lookup
2022-12-07 23:54:02 +0100 <dminuoso> The reflected type exists as a type itself
2022-12-07 23:54:11 +0100 <dminuoso> And you generate code by pattern matching on that type with typeclass instances.
2022-12-07 23:54:25 +0100 <dminuoso> And then there's a way to turn data into a generic representation
2022-12-07 23:54:31 +0100 <dminuoso> that you can do the same scrutinization on data level too
2022-12-07 23:54:43 +0100 <dminuoso> So we have hard to read/write code, that will compile extremely slowly
2022-12-07 23:54:52 +0100 <dminuoso> And then there's a generic represnetation that GHC may not be able to get rid of
2022-12-07 23:55:43 +0100 <tvandinther> I see, sounds interesting. A bit above my comfort level with Haskell still but good to be aware of.
2022-12-07 23:55:43 +0100 <dminuoso> And further, once you have a Generic instance, *everybody* can pry into your object, encapsulation no longer possible
2022-12-07 23:55:53 +0100 <dminuoso> Lots of bad ideas.
2022-12-07 23:56:10 +0100 <dminuoso> TemplateHaskell can achieve many of the same problems
2022-12-07 23:56:11 +0100 <festive_kurbus> sir this is a wendys
2022-12-07 23:56:19 +0100 <dminuoso> But its *much* faster, and can easily generate optimal code
2022-12-07 23:56:36 +0100huskle(~huskle@250.79-105-213.static.virginmediabusiness.co.uk)
2022-12-07 23:56:50 +0100 <tvandinther> Ah yep, sounds very familiar with the C# world. Reflection libraries are being replaced with codegen ones.
2022-12-07 23:56:57 +0100 <huskle> ghci> all (>0) $ map (flip noise [0.900001..0.90001]) [1..1000]
2022-12-07 23:56:57 +0100 <huskle> True
2022-12-07 23:57:19 +0100 <tvandinther> Thanks for your explanations. Gotta get back to my day job now though :)
2022-12-07 23:57:37 +0100litharge(litharge@libera/bot/litharge) (Quit: restarting)
2022-12-07 23:57:56 +0100litharge(litharge@libera/bot/litharge)
2022-12-07 23:59:30 +0100 <huskle> i cant see how it could possibly be getting negative values!!
2022-12-07 23:59:35 +0100king_gs(~Thunderbi@187.201.204.122) (Ping timeout: 264 seconds)