<    June 2018     >
Su Mo Tu We Th Fr Sa  
                1  2  
 3  4  5  6  7  8  9  
10 11 12 13 14 15 16  
17 18 19 20 21 22 _2_3  
24 25 26 27 28 29 30
00:00 <nitrix> I'll go eat and have my brain stir it all up nicely while I'm on autopilot :]
00:00 <nitrix> hpc: Thanks for the chit-chat :)
00:01 kvda joined
00:01 <hpc> oh!
00:01 <hpc> nitrix: check out agda's emacs integration sometime
00:02 <hpc> it's not exactly what you're thinking of, but it's quite nice regardless and maybe you'll get something from it
00:02 Guest89999 joined
00:02 Tops21 joined
00:02 <nitrix> Noted
00:03 revprez_ody joined
00:05 Tops2 joined
00:06 rprije joined
00:06 louispan joined
00:06 beauby joined
00:08 ammazza joined
00:11 Tops21 joined
00:11 cybai joined
00:13 rprije joined
00:14 Tops2 joined
00:17 tromp joined
00:20 conal_ joined
00:21 <* hackage> hoist-error - Some convenience facilities for hoisting errors into a monad http://hackage.haskell.org/package/hoist-error- (schalmers)
00:24 jpgarcia joined
00:25 xkapastel joined
00:25 weird_error joined
00:27 siraben joined
00:28 Tops21 joined
00:29 acarrico joined
00:30 siraben joined
00:30 jfredett joined
00:30 andyhuzhill joined
00:30 progfun_ joined
00:33 <jpgarcia> are there some good examples of all the power of haskell "dependen types" out there?
00:33 <jpgarcia> like HList but with modern techniques
00:33 Tops2 joined
00:34 <jpgarcia> I guess I'll release a good example soon, btw :)
00:35 pt1973 joined
00:36 fmixing joined
00:36 <pt1973> hello world
00:37 <shapr> goodbye world?
00:37 kasra joined
00:38 UnChallengeD joined
00:38 <aarvar> jpgarcia: you mean not-dependent types?
00:40 andreabedini joined
00:40 <jpgarcia> I mean faking them, yes
00:42 enterprisey joined
00:42 FreeBirdLjj joined
00:42 vovs03 joined
00:43 darkJedi joined
00:43 siraben joined
00:45 ebsen joined
00:47 kvda joined
00:48 conal_ joined
00:49 dan_f joined
00:50 cosmia joined
00:50 jmcarthur joined
00:50 ericsagn1 joined
00:52 DSM joined
00:53 louispan joined
00:53 granttrec joined
00:53 nighty- joined
00:55 tromp joined
00:55 youtmon joined
00:59 l8star joined
01:00 beauby joined
01:00 Khisanth joined
01:01 kvda joined
01:01 Kundry_Wag joined
01:01 kasra joined
01:02 conal_ joined
01:06 BalterNotz joined
01:07 markus1199 joined
01:08 nano_ joined
01:10 <enterprisey> what does it mean when you import a module with a unit afterwards, like this: import Foo ()
01:10 <fishythefish> you can specify a list of things to import from a module; that's an empty list
01:10 <enterprisey> what's the point?
01:10 <enterprisey> to make a dependency for the compiler?
01:10 <fishythefish> it'll import typeclass instances and nothing else
01:10 cybai joined
01:10 <enterprisey> k thanks
01:15 iAmerikan joined
01:15 trevorriles joined
01:16 sm joined
01:16 cjreynolds joined
01:16 diwo joined
01:17 plutoniix joined
01:18 xcmw joined
01:18 dented42 joined
01:21 Yuras joined
01:21 Rayben joined
01:21 zearen joined
01:24 hamishmack joined
01:24 danso joined
01:25 xcmw joined
01:26 rblaze joined
01:30 TipsyMe joined
01:31 harfangk joined
01:34 mizu_no_oto_work joined
01:34 swalladge joined
01:36 gestone joined
01:44 davr0s joined
01:45 clarity joined
01:46 diwo joined
01:47 hamishmack joined
01:49 rblaze joined
01:49 dented42 joined
01:52 cake_nbake joined
01:52 chat joined
01:56 andreabedini joined
01:57 dfeuer joined
02:00 <dfeuer> @ops
02:00 <lambdabot> Maybe you meant: pl oeis docs
02:00 hucksy joined
02:02 <nitrix> dfeuer: There's #haskell-ops shall you need it.
02:02 nshepper1 joined
02:03 refold joined
02:03 <infinisil> Every once in a while I turn off irc filters (Alt-- with weechat) and am amazed how there are people who don't use them
02:04 zdenal joined
02:06 cake_nbake left
02:08 <infinisil> glguy: Huh, why did they get the +b? I must be missing something
02:08 fmixing joined
02:09 <shapr> silly question, "stack repl" gives me both Main and Lib in scope in ghci, but cabal new-repl exe:project does not, is there a way to get that same thing with new-repl?
02:09 <dfeuer> Thanks, glguy.
02:10 hamishmack joined
02:11 <shapr> ah, google says I can do ":module Main" in new-repl
02:12 diwo joined
02:16 Linter joined
02:16 kvda joined
02:18 rasusto_ joined
02:18 obi_jan_kenobi_ joined
02:18 worch joined
02:19 banc joined
02:21 Linter joined
02:25 davr0s joined
02:25 mizu_no_oto_work joined
02:28 Vapeur joined
02:31 zdenal joined
02:32 replay joined
02:33 Kundry_Wag joined
02:35 dfeuer joined
02:36 lagothri1 joined
02:38 chat_ joined
02:43 chat joined
02:43 tromp joined
02:46 drbean joined
02:49 <* hackage> hw-kafka-avro 2.0.0 - Avro support for Kafka infrastructure http://hackage.haskell.org/package/hw-kafka-avro-2.0.0 (alexeyraga)
02:50 dogweather joined
02:51 mkoenig joined
02:52 tzemanovic joined
02:53 chat_ joined
02:58 cjreynolds joined
02:58 fmixing joined
02:59 woodson joined
03:01 markhuge joined
03:01 dark904 joined
03:02 canaria joined
03:03 dogweather joined
03:06 gestone joined
03:06 lambda-11235 joined
03:09 diwo joined
03:11 acertain joined
03:11 kvda joined
03:12 cybai joined
03:12 rprije joined
03:14 canaria joined
03:15 Map joined
03:16 rasusto_ joined
03:19 saurabhnanda joined
03:20 louispan joined
03:20 dogweather joined
03:21 otto_s joined
03:21 obi_jan_kenobi_ joined
03:21 <nitrix> shapr: Try only "cabal new-repl"? I think the issue is the "exe:project" more than anything else.
03:22 zaquest joined
03:22 <shapr> I tried that, only Lib was in scope
03:22 <nitrix> :(
03:22 <shapr> but :module Main works
03:22 progfun joined
03:22 <* shapr> shrugs
03:23 lortabac_ joined
03:23 nitrix left
03:30 Destol joined
03:33 floryst joined
03:33 davr0s joined
03:35 lassulus_ joined
03:37 bbrodriguez joined
03:39 amelliaa joined
03:42 dogweather joined
03:48 mnoonan_ joined
03:48 kapil___ joined
03:49 fmixing joined
03:50 dogweather joined
03:52 khilan joined
03:52 refold joined
03:53 StoneToad joined
03:57 kvda joined
03:58 AetherWind joined
03:58 MoarSpaceFi joined
03:59 AetherWind left
04:01 edmundnoble joined
04:03 altjsus joined
04:03 path[l] joined
04:04 kvda joined
04:04 <* hackage> avro - Avro serialization support for Haskell http://hackage.haskell.org/package/avro- (alexeyraga)
04:04 Linter joined
04:05 vmandela joined
04:06 Scip joined
04:09 louispan joined
04:11 <* hackage> hw-rankselect - Rank-select http://hackage.haskell.org/package/hw-rankselect- (GeorgeWilson)
04:16 AetherWind joined
04:17 mac10688 joined
04:20 fmixing joined
04:21 aarvar joined
04:22 fmixing joined
04:25 tsaka__ joined
04:26 zar joined
04:27 fvr joined
04:28 ddellacosta joined
04:30 dented42 joined
04:31 tromp joined
04:33 kvda joined
04:42 mkoenig_ joined
04:45 lastmanstanding joined
04:45 andreabedini joined
04:47 ccomb joined
04:49 slack1256 joined
04:56 ccomb joined
04:58 sigma_ joined
05:01 acertain joined
05:02 <sigma_> is Data.HashTable.IO threadSafe ??
05:02 seangrove joined
05:02 zdenal joined
05:04 takuan joined
05:04 <cocreature> sigma_: no
05:05 justanotheruser joined
05:05 mcspud joined
05:05 xtreak joined
05:05 <sigma_> cocreature : what about ST version of the same table "Data.HashTable.ST.Cuckoo"
05:05 <dminuoso> cocreature: What is the basis for that assessment?
05:07 Ariakenom joined
05:07 <glguy> there aren't any primitives in ST for making things threadsafe, and that package does things in ST and then slams the result into IO
05:07 <cocreature> dminuoso: the basis is that it relies on things like MutableArray which are not thread safe
05:07 <cocreature> sigma_: you can’t use ST in a multithreaded context
05:08 <sigma_> cocreature : what do you mean by that ?
05:08 <sigma_> cocreature : if no that can i put my IO hashtable into a Tvar to make it thread safe ??
05:09 <cocreature> sigma_: the universally quantified "s" type parameter in ST prevents you from escaping a reference created in ST to another thread
05:09 <cocreature> yeah putting it in a TVar is perfectly fine
05:09 <cocreature> or probably an MVar
05:10 <cocreature> since modifyTVar is not going to be enough here
05:10 <sigma_> cocreature : which is better sounds similar to me, just that Tvar allows atomic updates ??
05:10 kuttifunk joined
05:11 <cocreature> but I would benchmark to see if you aren’t better off using a TVar and something like Data.Map or Data.HashMap
05:11 <cocreature> you need some way to block readers and other writers while you modify the HashMap in IO
05:12 <cocreature> for an MVar you can just use takeMVar to do so and putMVar once you’re done
05:12 <cocreature> but Data.HashTable is really not that fast for a lot of usecases ime and in a multithreaded context, I wouldn’t be surprised if it ends up being even slower than Data.Map or Data.HashMap
05:13 connrs joined
05:14 <sigma_> cocreature : how about how about "STMContainers.Map"
05:14 <cocreature> I’ve never used stm-containers so I can’t comment on the performance of that
05:15 <cocreature> I would start with a TVar on top of Data.Map or Data.HashMap (or Data.IntMap if you have integer keys) and see if it becomes a bottleneck
05:17 <sigma_> cocreature : okay everything you said make sense but i couldn't understand why Mvar would be preferred over Tvar ??
05:17 <cocreature> sigma_: how would you do an update of a mutable HashTable using a TVar?
05:18 <sigma_> but Data.Map is not mutable right >?
05:18 <cocreature> right, that’s why I said for Data.Map a TVar is fine
05:19 <cocreature> but for Data.HashTable.IO you are going to have a hard time with a TVar
05:19 <sigma_> ok so in a immutable context Tvars are preferable over Mvar right ?
05:20 progfun joined
05:20 DarkUnicorn joined
05:20 <cocreature> it really depends on your usecase. MVars and TVars do not represent the same thing since MVars can be empty
05:20 <cocreature> also the performance varies depending on your access pattern
05:21 canaria joined
05:22 <sigma_> cocreature : last question is "STMContainers.Map" is mutable right ?
05:24 <* hackage> hw-dsv 0.2 - Unbelievably fast streaming DSV file parser http://hackage.haskell.org/package/hw-dsv-0.2 (GeorgeWilson)
05:27 zdenal joined
05:28 johnw joined
05:29 canaria joined
05:31 sighingnow joined
05:35 bbrodriguez joined
05:43 Linter joined
05:49 cur8or joined
05:49 hellozee joined
05:54 vukonen joined
05:54 blankhart joined
05:55 tzemanovic joined
05:57 _vaibhavingale_ joined
05:58 karlguy_ joined
05:58 woodson joined
05:59 slomo joined
05:59 slomo joined
05:59 saurabhnanda joined
06:02 lugh joined
06:05 lugh joined
06:06 slaznick joined
06:07 keepLearning512 joined
06:08 andreabedini joined
06:10 ru0mad joined
06:12 codesoup joined
06:12 Vapeur joined
06:13 pranaysashank joined
06:13 pranaysashank left
06:13 connrs joined
06:14 pranaysashank joined
06:14 pranaysashank left
06:14 pranaysashank joined
06:14 pranaysashank left
06:16 ozzymcduff joined
06:16 xtreak joined
06:18 fvr joined
06:19 tromp joined
06:21 cybai joined
06:21 bertschneider joined
06:22 _vaibhavingale_ joined
06:23 yoneda joined
06:24 <sigma_> what does it mean when we say "streaming of monadic data structures."
06:29 slack1256 joined
06:33 arkaros joined
06:33 gregberns joined
06:33 hellozee joined
06:33 connrs joined
06:33 zdenal joined
06:34 phenoble joined
06:35 codyw joined
06:36 <pavonia> Possibly infinitely nested monadic actions yielding a result at each level, I guess
06:36 siraben joined
06:37 <dminuoso> :t fixM
06:37 <lambdabot> error:
06:37 <lambdabot> • Variable not in scope: fixM
06:37 <lambdabot> • Perhaps you meant ‘fix’ (imported from Data.Function)
06:37 <dminuoso> :t mfix
06:37 <lambdabot> MonadFix m => (a -> m a) -> m a
06:37 <dminuoso> :t fix
06:37 <lambdabot> (a -> a) -> a
06:39 robstr joined
06:39 dfeuer joined
06:41 canaria joined
06:42 danso joined
06:45 acidjnk joined
06:52 betawaffle joined
06:52 ogrady joined
06:54 charukiewicz joined
06:55 path[l] joined
06:55 nickolay_ joined
06:55 tsaka__ joined
06:56 LiaoTao joined
06:57 Unhammer joined
06:57 tombusby joined
06:58 keegans joined
06:58 <charukiewicz> I'm using Servant and Persistent for a RESTful API. The data types that Persistent produces when I define my database schema are not representative of the JSON I want to send back to the API consumer. Should I define intermediary types that do? Or is this something that can be handled by writing JSON encoders?
06:59 tomboy65 joined
07:00 <dminuoso> charukiewicz: Dont rely on the generic fromJSON/toJSON implementations.
07:00 <dminuoso> Or work with an intermediate type. =)
07:00 <tdammers> charukiewicz: my approach with these things is to have 3 sets of types. one set to represent what's in the database, one set to represent API data structures, and one set to represent the actual domain entities
07:00 encod3 joined
07:01 <tdammers> if you try and use the same type for all of them, you tend to get implicit coupling between the DB and the API, and that's going to come back and bite you as your application evolves
07:02 <tdammers> you can sometimes get away with just the domain objects though, if your DB and API instances are malleable enough
07:02 <charukiewicz> tdammers: the 'domain entities' being the actual 'business logic' that my haskell code works with?
07:02 eminhi joined
07:03 osa1 joined
07:03 dogweather joined
07:03 <tdammers> charukiewicz: yes.
07:03 davr0s joined
07:04 <tdammers> business logic == domain logic, same thing. I just prefer the term "domain logic" because not all software is business software ;)
07:05 tzemanovic joined
07:05 LiaoTao joined
07:06 vlatkoB joined
07:07 chele joined
07:07 <charukiewicz> so in such an approach, suppose we start at querying the db, you would write toDomainEntity and toApiEntity functions that transform the data to take values of the appropriate types? then I assume you could use the generic (or very close to) toJSON implementation at the end for the API endpoint response.
07:08 fujiy joined
07:09 <tdammers> something like that, yes
07:10 <tdammers> but the big advantage is that you no longer need a 1:1 correspondence between result sets, domain objects, and API responses
07:10 woodson_ joined
07:10 woodson__ joined
07:11 <tdammers> e.g., you could run multiple queries to get information about one user, combine that into one domain object, and then calculate some more data in other domain objects, and finally assemble an API response that contains only a subset of the user data but also fields from other domain objects
07:12 <charukiewicz> makes sense. thank you. and I agree with your point about the 'domain' vs. 'business' logic!
07:13 Dabo joined
07:13 Folkol joined
07:13 Cthalupa joined
07:16 plutoniix joined
07:17 harfangk joined
07:17 <BalterNotz> q
07:17 Boomerang joined
07:18 dogweather joined
07:18 Yuras joined
07:20 tromp joined
07:22 lortabac_ joined
07:24 <* hackage> prettyprinter 1.2.1 - A modern, easy to use, well-documented, extensible pretty-printer. http://hackage.haskell.org/package/prettyprinter-1.2.1 (quchen)
07:24 tv1 joined
07:25 lastmanstanding joined
07:25 tomboy64 joined
07:25 Linter joined
07:25 raichoo joined
07:27 tv2 joined
07:27 tomboy64 joined
07:28 dogweather joined
07:29 ThomasLocke joined
07:30 connrs joined
07:32 <* hackage> snap-language - Language handling for Snap http://hackage.haskell.org/package/snap-language- (petterb)
07:33 logzet joined
07:36 thc202 joined
07:37 osa1 joined
07:37 zakora joined
07:38 canaria joined
07:39 Ariakenom joined
07:41 vurtz joined
07:41 canaria joined
07:42 yeevy joined
07:42 curious_corn joined
07:43 path[l] joined
07:43 atodorov joined
07:44 <dminuoso> Mmm. What's the proper way to extract the executable from a new-style build for deployment purposes?
07:44 <cocreature> dminuoso: "cabal-plan list-bins" is probably your best option atm
07:44 <cocreature> (cabal-plan is a separate tool)
07:44 <atodorov> hi folks, I have a cabal package (tarball) which is a dependency of another program that I'm building. How can I instruct cabal to use the local tarball if found and fetch the rest via the Internet? This is part of a test pipeline where I want to make sure changes to the library don't break something in the application. Thanks.
07:45 progfun joined
07:49 asheshambasta joined
07:50 codyw joined
07:50 sarna joined
07:51 mansalss joined
07:53 <cocreature> atodorov: sounds like you might be looking for cabal’s optional-packages feature https://cabal.readthedocs.io/en/latest/nix-local-build.html#cfg-field-optional-packages
07:53 <cocreature> although that won’t take a tarball, so you’ll have to do the unpacking yourself
07:53 <cocreature> but if it’s part of the test pipeline, just fixing the version via some constraint sounds like it might be the better option
07:54 <cocreature> you can use "cabal new-freeze" to generate a freeze file that locks all package versions
07:54 <Boomerang> Alternatively if you use stack or nix, you should be able to point straight at the local tarball
07:55 <Boomerang> For stack: https://docs.haskellstack.org/en/stable/yaml_configuration/#archives-https-or-local-filepath
07:57 louispan joined
07:57 RegEchse joined
08:01 jhrcek joined
08:02 <* hackage> data-diverse - Extensible records and polymorphic variants. http://hackage.haskell.org/package/data-diverse- (louispan)
08:03 Folkol joined
08:06 hellozee joined
08:07 spion- joined
08:09 <dminuoso> cocreature: cabal-plan looks great thank you =)
08:09 keepLearning512 joined
08:09 tzemanovic joined
08:12 curious_corn joined
08:17 louispan joined
08:18 <* hackage> distributed-fork, distributed-fork-aws-lambda (utdemir): https://qbin.io/jews-plugin-6u3i
08:18 Gretchko1230 joined
08:19 <dminuoso> cocreature: What is the reason there's no infrastructure to pull the images out anyway? Is that because of the nix mentality?
08:20 <dminuoso> Or is it a result of it being beta and missing features?
08:20 <cocreature> dminuoso: afaik it’s more a case of “nobody has implemented it” :)
08:20 <dminuoso> Ah I see. :)
08:21 tzemanovic joined
08:21 <cocreature> I suppose eventually "new-install" might be what you should be using for deployment
08:22 <dminuoso> It seems like the cabal folks are actively designing new-install at the moment https://github.com/haskell/cabal/issues/4558
08:23 <cocreature> yeah, I think it’s a gsoc project
08:27 curious_corn joined
08:28 <* hackage> postmark-streams - Send email via Postmark using io-streams. http://hackage.haskell.org/package/postmark-streams- (petterb)
08:28 uberman joined
08:28 vazark joined
08:28 xtreak joined
08:29 vazark joined
08:30 slomo_ joined
08:30 Nussi joined
08:32 hamishmack joined
08:33 ijks joined
08:33 tauta joined
08:34 saurabhnanda joined
08:35 slomo joined
08:36 reactormonk joined
08:37 refold joined
08:37 dogweather joined
08:38 tzemanovic joined
08:39 ijks_ joined
08:39 bbear joined
08:40 Dabo joined
08:42 <* hackage> bustle 0.7.1 - Draw sequence diagrams of D-Bus traffic http://hackage.haskell.org/package/bustle-0.7.1 (WillThompson)
08:42 <atodorov> cocreature: this looks like what I need so I gave it a try. As far as I can tell from the default settings I just need to unpack the library into the current directory of the program and run cabal install && cabal build. However the log tells me Downloading library, Configuring, etc. So it looks like cabal downloaded the library from Hackage.
08:42 <cocreature> atodorov: that feature only works with cabal new-build
08:42 <atodorov> I will experiment more with that b/c I'm not sure I'm doing everything correctly. Any hints are appreciated
08:43 <cocreature> make sure the path is correct, don’t use "cabal install" and replace "cabal build" by "cabal new-build"
08:46 rprije joined
08:47 tzemanovic joined
08:48 hamishmack joined
08:51 arkaros joined
08:52 drets joined
08:53 <drets> Is there a function in standard library which gives me the Just first element from the list if it exists, otherwise Nothing?
08:54 <cocreature> :t listToMaybe
08:54 <lambdabot> [a] -> Maybe a
08:54 <cocreature> ^ drets
08:55 <drets> Oh, I saw it in hoogle, but the name... couldn't guess that it's the thing, thank you.
08:55 fendor joined
08:55 <Taneb> drets: it's not the best name
08:55 <cocreature> hoogle also shows you the first line of the docs which should be sufficient in this case :)
08:56 nyberg joined
08:56 <drets> I would name it maybeHead. =)
08:56 <cocreature> there is headMay in the "safe" package
08:56 alex`` joined
08:56 <dminuoso> drets: there's also pattern matching which depending on the usage might be nicer to read than listToMaybe
08:57 kosc_job joined
08:58 language_agnosti joined
08:58 bo joined
09:03 nwf joined
09:04 saurabhnanda joined
09:08 progfun joined
09:09 tsaka__ joined
09:12 louispan joined
09:15 louispan joined
09:20 tzemanovic joined
09:22 <jle`> some people call it safeHead
09:22 djtyml joined
09:23 <dminuoso> listToMaybe has a nice NT ring to it =)
09:24 <fendor> > headMay []
09:24 <lambdabot> error:
09:24 <lambdabot> Variable not in scope: headMay :: [a0] -> t
09:25 <drets> Cool, next nooby question: I have line 1: maybeScenarioId <- listToMaybe <$> (runPersist pool $ ... line 2: let foo = maybe Nothing (Just . E.unValue) maybeScenarioId. It feels I can refactor `maybe` somehow :thinking_face:
09:25 <quicksilver> foo = E.unvalue $> maybeScenarioId
09:26 <quicksilver> erm
09:26 <quicksilver> foo = E.unvalue <$> maybeScenarioId
09:26 seangrove joined
09:26 <fendor> @let headMay as = if null as then Nothing else Just (head as)
09:26 <lambdabot> .L.hs:166:1: warning: [-Woverlapping-patterns]
09:26 <lambdabot> Pattern match is redundant
09:26 <lambdabot> In an equation for ‘headMay’: headMay as = ...
09:26 <fendor> > headMay []
09:26 <lambdabot> Nothing
09:27 LiaoTao joined
09:27 <drets> quicksilver, cool, that works, can I remove the line 2 completely? and do something with first one?
09:28 <jle`> drets: yes, `maybe Nothing (Just . f)` is `fmap f`
09:28 <quicksilver> and <$> is just a way of writing fmap as an infix operator
09:29 <jle`> you can combine the two lines doing `fmap f . listToMaybe <$> ....`
09:29 <quicksilver> (to illuminate the connection between jle`'s answer and mine)
09:29 ijks joined
09:29 <quicksilver> interestingly it doesn't matter which order you do `fmap f` and `listToMaybe`
09:29 <jle`> maybeScenarioId <- fmap E.unValue . listToMaybe <$> runPersist ....
09:29 <quicksilver> so `listToMaybe . fmap E.unvalue` would work too
09:30 <jle`> yup, because listToMaybe is a natural transformation :)
09:30 saurabhnanda joined
09:30 <quicksilver> :category_theory_high_five:
09:30 <drets> jle` thank you works, I tried ((E.unValue . listToMaybe) <$>...) and E.unValue <$> listToMaybe <$> ... and it didn't =)
09:30 cur8or joined
09:30 <jle`> that's a part of the reason why i like the listToMaybe name, because it emphasizes the fact that it's a natural transformation
09:31 <jle`> yeah it'd be (E.unValue <$>) . listToMaybe <$> ... if you had to use <$>
09:31 <jle`> definitely a lot less readable in this situation heh
09:31 <drets> So close, no matter how far =)
09:32 <quicksilver> yeah the fmap at two different levels is mildly unaesthetic
09:32 uberman joined
09:37 catsup joined
09:37 language_agnosti joined
09:37 nschoe joined
09:37 canaria joined
09:37 kuribas joined
09:38 dhil joined
09:38 codyw joined
09:39 catsup joined
09:41 cybai joined
09:43 saurabhnanda joined
09:43 buzo joined
09:46 keepLearning512 joined
09:46 lonokhov joined
09:47 Psybur joined
09:47 henriksod joined
09:49 mkoenig joined
09:50 reactormonk joined
09:51 lumm joined
09:51 zero_byte joined
09:52 ma27 joined
09:53 simukis joined
09:53 progfun joined
09:54 przembot joined
09:55 Linter joined
09:55 fmixing joined
09:56 jdt joined
09:56 <Philonous> Is there an easy way to get the IOErrorType of an IOException ?
09:56 kapil___ joined
09:57 dddddd joined
09:57 oish joined
09:58 <rkrishnan> is "cabal new-run" functional? I have this cabal.project file that has two packages in it (with .cabal file), when I run "cabal new-run foo", all I get is "Up to date". It does not actually run the program.
09:59 <cocreature> rkrishnan: which version of cabal are you using?
09:59 <rkrishnan> (cabal library is
09:59 <cocreature> you need 2.2 for a working new-run
09:59 <arahael> What's wrong with this expression?
09:59 <rkrishnan> ah, ok, thanks a lot, cocreature. WIll compile it now.
09:59 <arahael> \(a, b) -> a / b $ zip [1.1] [2.2]
10:00 canaria joined
10:00 <arahael> (I expect to see [0.5] as the answer)
10:00 <cocreature> rkrishnan: in general if you’re using the new-* stuff you want to make sure you are using the latest version or even run from HEAD
10:00 <cocreature> Philonous: how about ioeGetErrorType?
10:00 piyush-kurur joined
10:00 <rkrishnan> cocreature: thanks.
10:01 <Philonous> cocreature, Yes, I just saw it. -_- Sorry
10:01 <cocreature> arahael: you forgot a "map"
10:01 <arahael> cocreature: D'oh. Indeed.
10:02 <quicksilver> > \(a, b) -> a / b <$> zip [1.1] [2.2]
10:02 <lambdabot> error:
10:02 <lambdabot> • No instance for (Typeable b0)
10:02 <lambdabot> arising from a use of ‘show_M59217637781609940133003’
10:02 <cocreature> arahael: you might also want to use zipWith instead of zip + map
10:02 <arahael> cocreature: Ideally, I wanted to have: zip [1.1] [2.2] `something` (\(a, b) -> a / b)
10:02 <arahael> cocreature: But I don't knwo what to use for 'something'.
10:03 <quicksilver> > (\(a, b) -> a / b) <$> zip [1.1] [2.2]
10:03 <lambdabot> [0.5]
10:03 ma27 joined
10:03 <arahael> quicksilver: Right, but I want a `flip <$>`, if that makes sense.
10:03 <quicksilver> it does
10:03 machinedgod joined
10:04 <quicksilver> the lens library is full of combinators which work that way around
10:04 <arahael> Ah, that must be why they don't show in hoogle (by default)
10:04 <cocreature> we even have it in base by now!
10:04 <cocreature> :t (<&>)
10:04 <lambdabot> Functor f => f a -> (a -> b) -> f b
10:05 <cocreature> > zip [1.1] [2.2] <&> (\(a,b) -> a / b)
10:05 TipsyMe joined
10:05 <lambdabot> [0.5]
10:05 <arahael> Nice, not in my haskell, sadly.
10:05 <cocreature> but I’d say that’s still worse than zipWith
10:05 <cocreature> > zipWith (/) [1.1] [2.2]
10:05 <lambdabot> [0.5]
10:06 <arahael> cocreature: That works with tuples like that!?
10:06 <cocreature> :t zipWith
10:06 <lambdabot> (a -> b -> c) -> [a] -> [b] -> [c]
10:06 <cocreature> it’s basically zipWith + map
10:06 <arahael> Ah, very nice.
10:08 curious_corn joined
10:09 seangrove joined
10:12 arkaros joined
10:14 averell joined
10:18 kuttifunk1 joined
10:21 Psybur joined
10:22 soupladler joined
10:23 louispan joined
10:23 jdt joined
10:23 silver joined
10:27 codyw joined
10:28 zero_byte joined
10:28 <maerwald> I think haskell needs a crowdfunded project to fix the tooling mess, especially wrt editor support
10:28 averell joined
10:28 knupfer joined
10:29 matsurago joined
10:30 canaria joined
10:30 <dminuoso> maerwald: Haskell needs developers contributing to tooling instead of complaining about the lack.
10:30 <maerwald> what? how would that work without money and time
10:31 isidore joined
10:31 jdt joined
10:31 <maerwald> obviously, it doesn't, otherwise it would have happened already
10:31 UnChallengeD joined
10:32 <* quicksilver> has observed a lot of time (and probably money as well?) put into tooling and editor support over the last 10 years
10:32 <quicksilver> but, well, it's hard to get it right, and it's hard to get things finished
10:32 <electrocat> there are many things that are close to the tooling we need
10:33 <cocreature> even if you have something that seems finished at some point, the next GHC release will probably break it
10:33 <electrocat> we just never get there
10:33 <cocreature> or the release of yet another build tool will require updates, …
10:33 <maerwald> cocreature: yes, that has to be discussed to, external API shouldn't randomly break anymore
10:33 rzp joined
10:34 iAmerikan joined
10:34 <cocreature> that requires defining what the external API even is
10:34 <cocreature> and once you expose the AST which some tooling wants to look at you pretty much have to live with breaking changes
10:34 danso joined
10:34 KeyJoo joined
10:34 <maerwald> weird, that doesn't seem to be the case in other languages
10:34 <maerwald> as in: they don't constantly break the AST
10:35 KeyJoo joined
10:35 <electrocat> they don't change the language that often as we do :p
10:35 <dminuoso> All I want is type information for arbitrary expressions and gathering errors (and correlating them to source code with flycheck).
10:35 <Taneb> Haskell is foremost an exercise in language design research
10:35 <cocreature> dminuoso: that’s just ghci :)
10:35 <maerwald> Taneb: not anymore, no
10:35 <cocreature> and ghci has a pretty stable interface
10:35 <Taneb> It just happens to be an exercise in language design research that gets used
10:36 <dminuoso> cocreature: So I suppose ghcid is finally the answer Ive been avoiding.
10:36 <cocreature> dminuoso: or dante if you want something more integrated in emacs
10:37 <cocreature> or intero which isn’t much more than ghci for the most part either
10:37 <Taneb> maerwald: it's going to be until there are other mainstream general purpose non-strict languages
10:37 <maerwald> and doesn't have code completion
10:37 <dminuoso> Im not happy with intero, it's way too brittle and requires me to kill it so often..
10:37 <cocreature> ghci does have code completion
10:37 <dminuoso> And I suspect that intero is somewhat crash happy (since Ive been getting a lot of segfaults after using intero)
10:37 vonfry joined
10:38 Sampuka joined
10:38 <cocreature> % :complete repl 5 "import Data."
10:38 <yahb> cocreature: 5 313 "import "; "Data.Array"; "Data.Array.Base"; "Data.Array.IArray"; "Data.Array.IO"; "Data.Array.IO.Internals"
10:38 <dminuoso> Mmm dante looks good as a drop-in replacement :)
10:38 <dminuoso> intero-light almost
10:39 <maerwald> Taneb: it's not really that. It just happens that most people in the haskell community value stable API very little. It's not just GHC, it's also Cabal (supporting multiple versions is an ifdef hell) and others
10:39 <maerwald> and so tooling also becomes a mess
10:39 <maerwald> you can experiment anything you want in your internal API and do API-backwards compatible additions
10:39 <dminuoso> And furthermore, in all fairness what do you compare Haskells tooling to?
10:39 <maerwald> it's not that simple "oh, we are research"
10:40 <dminuoso> If you compare it to Java it's a bad case because Java has billions of dollars invested to by all kinds of companies all over the planet.
10:40 <maerwald> Java, in some areas, is much more research than haskell, because the type system is so extensible
10:40 <maerwald> that's a design problem
10:40 <maerwald> nothing else
10:41 Ariakenom joined
10:41 emilypi joined
10:42 <dminuoso> What non-Java languages have excelling tooling?
10:42 <maerwald> Go
10:42 <maerwald> for editors (not build system)
10:42 <LiaoTao> C++ :^)
10:42 canaria joined
10:43 arkaros joined
10:43 <dminuoso> LiaoTao: Are you referring to MSVC?
10:43 <maerwald> even clojures tooling seems better
10:43 <LiaoTao> I'm being glib again
10:43 <LiaoTao> C++ is a flaming mess
10:43 <dminuoso> heh
10:43 <LiaoTao> MSVC can be nice, though
10:43 <dminuoso> It's my experience that tooling for most languages is not really stellar.
10:44 <maerwald> I don't think so
10:45 <dminuoso> maerwald: What specific "tooling" features do you miss in Haskell that you think is prevalent in other languages
10:45 sqrt2 joined
10:45 pfurla joined
10:45 <cocreature> it’s not so much about missing features as it is about Haskell tooling being really brittle
10:45 jhrcek joined
10:45 <maerwald> it's not about what I miss, it's that they are constantly broken
10:46 <maerwald> they can neither keep up with GHC, nor Cabal
10:46 takuan joined
10:46 <maerwald> which also shows a cultural problem
10:46 <maerwald> library authors don't *care* what they break
10:46 <maerwald> "use the old version", pvp 4tw
10:48 <maerwald> which is why you are stuck with ghc 7.10 if you want to install ghc-mod (without checking out WIP branches, applying patches etc)
10:49 ijks_ joined
10:49 hphuoc25 joined
10:49 HarveyPwca joined
10:49 <maerwald> so either this needs a cultural shift, or a very active crowdfunded project
10:50 zar joined
10:51 fishythefish joined
10:51 Tourist joined
10:51 Tourist joined
10:52 sqrt2 joined
10:52 <rkrishnan> cocreature: thanks, new-run works great with cabal
10:55 youtmon joined
10:56 UnChallengeD joined
10:57 fmixing joined
10:57 sqrt2 joined
10:58 fendor joined
10:58 encod3 joined
11:01 encod3 joined
11:03 encod3_ joined
11:03 sqrt2 joined
11:03 cybai joined
11:03 <tdammers> the weird thing about Haskell's IDE story is that while in theory, the language offers excellent tooling opportunities, in practice none of them work
11:03 dogweath_ joined
11:03 son0p joined
11:04 <liste> and it's sad :(
11:04 <liste> though there's been some progress lately
11:04 <liste> with Language Server Protocol
11:04 <tdammers> I think part of the reason is our insistence on doing things right
11:05 <tdammers> most haskellers aren't keen on solutions that get you 80% there but make the remaining 20% impossible because the abstractions are technically wrong
11:06 dogweath_ joined
11:06 <tdammers> so for example, you can't really make correct autocompletion for Python, because there is no way of knowing what you'll *really* have in that object you're looking at without actually running the code on the production server
11:06 <tdammers> but you can make some educated guesses, and they're usually still much better than nothing, even if they're possibly outright wrong
11:07 <dminuoso> tdammers: That summarizes intellisense.
11:07 <dminuoso> In all its glory.
11:07 <tdammers> yes, pretty much
11:07 <quicksilver> on the other hand, C# has this interesting property that it is (very often) possible to read it left-to-right top-to-bottom and have correct type information
11:07 <dminuoso> tdammers: Though if thats all you care about, then ctags has you covered already.
11:07 <quicksilver> it's like C# is the perfect intellisense language
11:07 <tdammers> dminuoso: well, exactly, that's the other reason - we can't get 100%, so instead of settling for 80%, we settle for a more predictable 50%
11:08 howdoi joined
11:08 davr0s joined
11:08 <tdammers> quicksilver: in all fairness, C# was designed with intellisense in mind
11:08 sQVe joined
11:09 canaria joined
11:10 sqrt2 joined
11:10 karlguy_ joined
11:11 <quicksilver> tdammers: and vice versa
11:12 <quicksilver> tdammers: giving developers powerful tools was absolutely a key objective of that whole process. And that particular company has a lot of tool expertise.
11:12 slomo joined
11:12 slomo joined
11:12 <quicksilver> powerful <*> (combinators `applied` infix) need a different model.
11:12 errst joined
11:13 <dminuoso> quicksilver: That's an interesting consideration. In a way it's easier to create tooling for a language that has an artificial limit on the abstractions available. That is if `classes` are all the whizz of your language and the type system is rigid and not extensible, then the tooling gets easy.
11:14 <dminuoso> Because you force the users to do abstractions within those restrictions, giving rise to "patterns" in the sense of GoF.
11:14 Ariakenom joined
11:14 seangrove joined
11:14 Ariakenom joined
11:15 <cocreature> dunno, I don’t think the problems with Haskell’s tooling are caused by the restrictions or lack thereof in the language
11:15 <dminuoso> Im just suggesting it might at the very least be one factor
11:15 <quicksilver> cocreature: I don't think it's the whole story but I do think it's a factor.
11:16 louispan joined
11:16 <cocreature> I think it’s a factor that comes into play at a much later point
11:16 Yuras joined
11:16 <dminuoso> Also there's the part that in case of C# the language implementation and IDE are not separate product - they are one product coming from the same vendor.
11:16 <cocreature> our tooling breaks because of our build tools and the GHC api are changing
11:16 <cocreature> not because you can do profunctor lenses
11:16 <dminuoso> In the "open world" things are much uglier when A) gives you the compiler, B) gives you a build chain, C) gives you an editor and D) tries to glue everything together
11:17 <dminuoso> cocreature: But why is the GHC API changing so much?
11:17 emilypi joined
11:17 <cocreature> sure language changes are a problem but you can change a language that’s simple as well
11:18 sqrt2 joined
11:18 <cocreature> and I’d say that problem would be solvable if we would agree on what the public interface of the GHC API is even supposed to be. for now GHC exposes pretty much everything so people use everything and complain when it breaks
11:19 <quicksilver> for the syntax and type-checking problem, it would nice if there were public APIs for those two things
11:19 <cocreature> a significant part of the complexity in ghc-mod and the reason why it doesn’t work with new-build is just getting information out of your build tool
11:19 <quicksilver> concrete syntax tree and types
11:19 <quicksilver> and then new GHC features would 'have to' include corresponding updates to those two APIs (ASTs)
11:19 <cocreature> for types, you have ghci and for the syntax tree there is a gsoc project this year
11:20 <quicksilver> does ghci have a machine-readable type ?
11:21 dogweather joined
11:21 <cocreature> dunno, but most of the tooling just seems to present it to users so I’m not sure the fact that it’s machine readable matters for the tooling that we have to day (ofc you can definitely build tooling that does inspect the type but that’s the next step)
11:22 canaria joined
11:22 knupfer joined
11:23 <cocreature> my point is the problems with our tooling are at a much lower level than the one where the complexity of the language comes into play
11:23 curious_corn joined
11:24 <arkaros> cocreature: Just out of interest. What is the main paint-points that you think that the haskell tooling has?
11:25 <cocreature> ime the interaction with the build tools is the most annoying part
11:26 ozzymcduff joined
11:26 <arkaros> So how we compile the project and such?
11:26 sqrt2 joined
11:27 <cocreature> every tooling that uses the GHC api must figure out the arguments that it passes to ghc, that involves parsing the cabal file, figuring out package databases, …
11:27 tabaqui1 joined
11:27 <cocreature> if you actually want your tooling to work for all build tools that a significant portion of Haskellers use you need to get this right for at least cabal, cabal new-build, stack and nix
11:29 <dminuoso> Lets see if I can run `cabal new-build --only-depenencies` with everything but the .cabal file missing, and then copy the project into the directory and build it =)
11:30 <dminuoso> This is going to be interesting
11:30 <arkaros> Hmm it feels like a lot of languages have issues with the build tools and that a lot of languages have their own custom implementation of how to do builds.
11:31 <tdammers> quicksilver: the vice-versa case is kind of obvious - of course you write a smart autocompleter to match the target language; but designing the language so that it is an easy target for a smart autocompleter is kind of an intriguing idea
11:32 sqrt2 joined
11:32 pfurla_ joined
11:32 <Jinxit> yeah that's what i was worried about
11:32 <Jinxit> w/c
11:32 <dminuoso> arkaros: that's how MS does things: they give you the compiler, the IDE and build tools - all in one package
11:32 jeltsch joined
11:33 <quicksilver> tdammers: yes, and you can see how it informs their new features to.
11:33 <quicksilver> tdammers: "how will this new feature integrate into our refactoring tools and our code sense tools?"
11:33 <maerwald> liste: unfortunately, the most fundamental feature of LSP haskell doesn't work: type of arbitrary expressions
11:33 <quicksilver> tdammers: whereas in a heterogenous environment the answer to that double question is always "It will break them. All of them."
11:33 <maerwald> at least not in vim (supposedly in VS code)
11:33 alexteves_ joined
11:34 <maerwald> you can only get type of identifiers
11:34 <maerwald> which is pretty boring
11:35 <* hackage> wai-route 0.4.0 - Minimalistic, efficient routing for WAI. http://hackage.haskell.org/package/wai-route-0.4.0 (romanb)
11:36 <arkaros> dminuoso: Yeah sure but it feels like rather than using one of the existing build tools all languages sort of implement their own instead of building on existing and quite functional solutions. My knowledge in this area is way too lacking to actually argue for this point but it feels sort of like languages reinvent the wheel in order to hava build system written in the language currently used.
11:36 korans joined
11:36 errst joined
11:37 <arkaros> Like is there a reason why haskell couldn't just be built using gradle, for example?
11:37 <tdammers> quicksilver: indeed. it's a tradeoff.
11:37 dogweather joined
11:38 <maerwald> gradle? Please :>
11:38 <arkaros> Just throwing it out there.
11:38 sqrt2 joined
11:38 fishythefish joined
11:38 <gonz_> maerwald: The reason type of arbitrary expression doesn't work in neovim with HIE, for example, is because it fails on getting docs for the selection
11:39 <dminuoso> arkaros: One of the driving thoughts of Haskell is "everything out there sucks and is doing it wrong" (well maybe not as sharp..)
11:39 <maerwald> the only universal tool out there are Makefiles and theoretically you can use that for your haskell project, but it might be hard to really have useful abstraction (do you use cabal sandbox, new-repl or stack?)
11:39 <gonz_> and it doesn't try to salvage the error it gets for docs with showing the type
11:39 <gonz_> The language server analyzes the type and sends it back just fine
11:40 <gonz_> You select `writeToFile filename` and do show type on it, it gets the type but also tries to fetch docs for "writeToFile filename"
11:40 <gonz_> It's not a language server issue, but a client side issue
11:41 <maerwald> so I'm back to using plain ghc-mod
11:41 danthemyth joined
11:41 <maerwald> whatever you try, for some reason it doesn't work...
11:41 <maerwald> at this point, haskell fits very well in the unix ecosystem
11:41 <maerwald> :P
11:42 <Ariakenom> Feel like I need to link SPJ's https://www.microsoft.com/en-us/research/uploads/prod/2018/03/build-systems.pdf
11:42 <arkaros> maerwald: Sounds like a quite a dark realization. "whatever you try it doesn't work"
11:42 <quicksilver> arkaros: all build tools are horrible and broken. They all fail to solve the hard problems of dependency management (some of them also fail to solve some other easy problems)
11:42 canaria joined
11:42 <gonz_> The correct way for neovim-LanguageClient to do it would be to only get docs for the thing at point, but do expression on the entire selection, which is what VSCode does
11:42 <maerwald> Ariakenom: waaat, the first sentence is already wrong :>
11:42 <maerwald> make is neither big, nor complicated
11:42 encod3 joined
11:42 <quicksilver> arkaros: whenever a new language ecosystem springs up, people in that community believe that they can do better :)
11:42 <maerwald> autotools is
11:42 encod3 joined
11:43 sdothum joined
11:43 <Ariakenom> maerwald: make gets complicated
11:43 <Ariakenom> generating makefiles | recursive makefiles
11:43 <Ariakenom> ghah
11:43 <maerwald> generating?
11:44 canaria joined
11:44 <Ariakenom> yes, terrifying
11:44 <maerwald> how is that related to make
11:44 <maerwald> that's like saying "it's hard to generate haskell code"
11:44 <quicksilver> it's relative. Make is big and complicated relative to the core problem you want it to solve.
11:44 <quicksilver> but it's a complex discussion.
11:45 <maerwald> make is annoyingly simple
11:45 <Ariakenom> make is too bad at solving the issue so you need to generate makefiles, which has problems
11:45 <maerwald> which is why we came up with cancer like autotools
11:45 <maerwald> yes, it is simple, not complicated
11:45 <Ariakenom> eh
11:45 alex`` joined
11:45 philippD joined
11:46 <Ariakenom> it's simple like brainfuck is simple. if you try to use it to solve a problem its complicated.
11:46 <maerwald> simple tools are usually like that
11:47 tzemanovic joined
11:47 <Ariakenom> whether to call it itself simple is just a matter of phrasing.
11:47 <maerwald> it's a property
11:47 jdt joined
11:48 <maerwald> although, this is probably funny http://okmij.org/ftp/Computation/#Makefile-functional
11:48 <maerwald> maybe we can implement haskell in make
11:49 vurtz joined
11:50 remyhr joined
11:50 <juri_> i still think in makefiles. my haskell software comes with a Makefile.
11:52 fishythefish joined
11:54 RegEchse joined
11:54 seangrove joined
11:55 canaria joined
11:55 vukasink joined
11:57 tabaqui1 joined
11:58 trcc joined
11:58 aarvar joined
11:59 cybai joined
11:59 perspectival joined
12:00 <zincy> how do I drop a the elements within a list given a list of indices to drop at
12:00 jrabe joined
12:00 <juri_> you create a new list, without the element.
12:01 <cocreature> zincy: zip the list with the indices and then filter based on whether the index is in the list
12:01 canaria joined
12:01 <cocreature> zincy: but tbh that sounds like something for which you might want to use Data.Map rather than a list
12:03 <zincy> thanks
12:05 canaria joined
12:05 <zincy> https://lpaste.net/189407065616154624
12:05 <zincy> So I am stuck on how to get this algorithm to work.
12:06 HarveyPwca joined
12:06 <zincy> Given a list of players and a list of cards if a playerState is In then the player should be given two cards from the deck of cards. The end result is a tuple where the first element are the players and the second element is the cards remaining in the deck after the dealing process
12:08 <zincy> In that snippet the correct players are given the correct cards but what should be the remaining deck of cards is in fact just the original deck of cards. However as you know the intersection of the player cards and remaining cards should be empty
12:08 dogweather joined
12:08 KeyJoo joined
12:10 curious_corn joined
12:12 keepLearning512 joined
12:13 <* hackage> bgmax - Parse BgMax-files http://hackage.haskell.org/package/bgmax- (petterb)
12:15 keepLearning512 joined
12:16 davr0s joined
12:19 PatrickRobotham joined
12:19 ndeine joined
12:21 dogweather joined
12:21 <quicksilver> zincy: yes, you concat the entire chunkedDeck at the end
12:21 <quicksilver> so you do indeed get back the whole deck
12:21 <quicksilver> also note that if one your players isn't In (perhaps he's Out?) then his two cards still get skipped
12:22 <quicksilver> don't think you want to use zipWith here
12:22 arkaros joined
12:23 <* hackage> pidfile - Run an IO action protected by a pidfile http://hackage.haskell.org/package/pidfile- (petterb)
12:24 <zincy> quicksilver: correct we dont give players that are Out any cards
12:24 <zincy> im not sure what to use instead of zipwith
12:25 fryguybob joined
12:25 vonfry1 joined
12:25 Linter joined
12:27 Kacia joined
12:27 zdenal joined
12:30 encod3 joined
12:30 carlomagno1 joined
12:31 <hexagoxel> :t mapAccumL
12:31 <lambdabot> Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c)
12:31 <hexagoxel> zincy: ^
12:32 <quicksilver> zincy: I would personally rewrite that code in a more 'imperative' style
12:32 <quicksilver> using a state monad to handle the changes to the player states
12:32 <quicksilver> and returning the leftover deck
12:32 <zincy> hexagoxel: cool!
12:33 <zincy> quicksilver: I was thinking about that ... the functional style is prettier though isnt it if possible
12:33 <zincy> the imperative version in the state monad would probably be more performant
12:33 <quicksilver> nope
12:33 <quicksilver> the state monad *is* the functional style
12:33 dogweather joined
12:33 <quicksilver> it's just a different way of writing it
12:34 <quicksilver> the state monad is just a way to use monadic notation to construct functions (s -> (a,s))
12:34 <zincy> its a functional style *emulating* an imperative style right
12:34 <maerwald> it doesn't really feel functional, except for haskellers maybe
12:34 <maerwald> I would rather describe it "monadic style"
12:34 <maerwald> not many other functional languages use that style, so "functional" is kinda far-fetched
12:35 <zincy> maerwald: that is what I thought too I guess functional is a bit of a fuzzy term though
12:35 seangrove joined
12:36 <maerwald> it's not necessarily fuzzy, except when people stuff things like "purity" into it
12:36 <zincy> is that people people conflate evaluation and executon of haskell programs
12:36 <Ariakenom> or first class functions
12:36 <maerwald> they conflate functional with purely functional
12:36 <hexagoxel> for learning purposes, or before one thinks of mapAccum, there always is plain recursion.
12:36 pspace joined
12:37 <pspace> hi everybody can you hear me?
12:37 <zincy> whats the difference between functional and purely functional
12:37 <zincy> cant hear you :P
12:37 <pspace> :D
12:38 <maerwald> zincy: functional is just "based on lambda calculus", which is very broad, not saying much about evaluation properties
12:38 <zincy> People call javascript functional
12:39 <maerwald> is it based on lambda calculus?
12:39 <zincy> because functions are first class
12:39 omilu joined
12:39 <zincy> maerwald: Its pure lambda calculus all the way down
12:39 <maerwald> then it's certainly functional
12:39 <zincy> haha
12:40 <pspace> purly functional is without any global state and effectless/side effects in monads
12:40 <maerwald> nah
12:40 <zincy> I always thought the "if it has first class functions it is a functional lang" was always a loose criteria since nearly every lang has that
12:40 <dminuoso> pspace: Nope
12:40 <dminuoso> pspace: Haskell had side effects long before monads were even known to programmers.
12:40 <pspace> ok than i am sorry
12:40 <zincy> haskell does have side effects right?
12:41 <dminuoso> pspace: Purely functional only means that your functions are referentially transparent.
12:41 <maerwald> zincy: http://citeseerx.ist.psu.edu/viewdoc/download?doi=
12:41 <zincy> They are just controlled
12:41 <dminuoso> zincy: a language without side effects is not going to be a very useful one
12:41 <maerwald> purely functional means that call-by-name, call-by-need and call-by-value are weakly equivalent
12:42 <zincy> I think john carmack needs to read this he said you can do functional programming in C++
12:42 <maerwald> functional programming != functional language
12:42 <maerwald> and indeed, he is right
12:42 <dminuoso> maerwald: what does the evaluation model have to do with being purely functional?
12:42 <zincy> ahhh
12:42 <maerwald> dminuoso: see the link
12:43 nitrix joined
12:43 petermw joined
12:43 <zincy> What is this notation
12:43 <zincy> M; N; L 2 Term ::= x j x:M j MN j n j M + N
12:43 <dminuoso> maerwald: Thats a necessary but not sufficient definition according to the paper.
12:44 <maerwald> dminuoso: what do you mean?
12:44 cloudhead joined
12:45 thongpv3 joined
12:45 <zincy> Would I be correct if I said the lambda calculus was a system of compution based on unary functions
12:45 <thongpv3> Hello everybody, I'm new to Haskell
12:45 <maerwald> dminuoso: think of it this way, when the evaluation strategy "doesn't matter", then it cannot have "side effects", right? (that's a very fuzzy interpretation, but...)
12:46 Sampuka_ joined
12:46 connrs_ joined
12:46 yeevy_ joined
12:46 <maerwald> also note "weakly equivalent", because of laziness
12:47 <thongpv3> What is good book for learning haskell
12:47 <* hexagoxel> might consider "side effects" versus "effects"
12:47 <dminuoso> thongpv3: what background do you have in programming and functional programming?
12:47 <maerwald> hexagoxel: the problem is that "return a value" is also considered an "effect" for most people
12:47 john883 joined
12:47 <zincy> thongpv3: https://www.amazon.co.uk/Programming-Haskell-Graham-Hutton/dp/1316626229/ref=sr_1_1?ie=UTF8&qid=1529066864&sr=8-1&keywords=hutton+haskell
12:48 mkoenig_ joined
12:48 umpc joined
12:48 yumh joined
12:48 crobbins joined
12:49 <thongpv3> I'm good at C++, I know what is algebraic data type, pattern matching, concept, first class function
12:49 <dminuoso> thongpv3: Are you experienced with any ML type of languages?
12:50 <thongpv3> No
12:50 <dminuoso> thongpv3: Curious, where does your ADT and pattern matching experience come from?
12:50 HarveyPwca joined
12:50 <thongpv3> from C++ variant, optional.
12:51 john883 joined
12:51 <nitrix> thongpv3: My typical recommendation is http://haskellbook.com/. The author went through a lot of efforts to consolidate all the material scattered online in an approachable way, regardless of your background.
12:52 <thongpv3> I know litte of template meta programming in C++ (partial template specialization is look like pattern matching, concepts is looklike typeclass)
12:52 <zincy> does anyone else find haskelbook way way too slow
12:52 yumh joined
12:52 <dminuoso> thongpv3: CIS194 might be suited to you, it's a bit dense and has good excercises.
12:52 <dminuoso> zincy: It's targeted towards beginners to programmers.
12:52 <matsurago> I found "Get Programming with Haskell" quite useful with good examples.
12:52 ziyourenxiang_ joined
12:52 <zincy> hmm I wouldnt call myself advanced
12:53 <nitrix> zincy: I prefer that it holds your hand, with examples and assignments that you must complete on your own, rather than skimming material too fast and creating an opportunity for the reader to think they grasp the concepts when they don't really.
12:53 <maerwald> zincy: the proprietary book?
12:54 <dmwit> zincy: That notation is BNF. It says that in the future, they plan to use "M", "N", and "L" as metavariables for the syntactic category they're defining there, and that the syntactic category includes five syntactic forms.
12:54 <maerwald> I even find lyah too slow
12:54 <zincy> maerwald: whats that?
12:54 <dmwit> zincy: I find your description of the lambda calculus as "based on unary functions" kind of misses the point but isn't technically incorrect.
12:54 <maerwald> something you shouldn't read
12:54 <dminuoso> thongpv3: Did you have any contact with the C++ ISO standard?
12:54 <zincy> nitrix: The exercises are great
12:55 <maerwald> I want: 1. core concept, 2. motivation, 3. one use case, 4. exercises
12:55 <maerwald> no BS, no blah
12:55 <matsurago> Well, I would definitely not recommend LyaH
12:55 <dmwit> maerwald: That is why I loved the Gentle Introduction.
12:55 <zincy> maerwald: Yes
12:55 <dminuoso> +1
12:55 <dmwit> maerwald: Straight to the point, no BS. I also couldn't stand LYAH for exactly the same reasons.
12:55 mizu_no_oto_work joined
12:55 <matsurago> LyaH was a reason I didn't learn Haskell for long long time.
12:55 <zincy> I feel like whoever wrote haskelbook has very little actual writing experience
12:55 <thongpv3> @dminuoso no, but I keep track at C++
12:55 <lambdabot> Unknown command, try @list
12:55 <maerwald> haha
12:55 <zincy> *haskellbook
12:56 <dmwit> ?where gentle
12:56 <lambdabot> http://www.haskell.org/tutorial/
12:56 keegans joined
12:56 sheyll joined
12:56 <dminuoso> thongpv3: You might find CIS194 to your liking. You should, regardless of what learning resource you pick, keep a copy/link to the Haskell 2010 report at hand. It's for the most part easily readable and can often help illuminate things.
12:57 <dmwit> thongpv3: (And if you don't mind separating the process of learning the language from learning the libraries, I still recommend the Gentle Intro for learning the language. It is out of date when commenting on the libraries, though.)
12:57 <dminuoso> The gentle introduction just doesn't teach you any functional programming at all.
12:57 <* dmwit> shrugs
12:57 <dmwit> Worked for me.
12:58 <nitrix> Haskell is indeed very terse with quite overwhelming abstractions when you're new to all this. I think it's good that it's slow. Otherwise you have the illusion that you understand, but you still fumble for weeks, trying to put the pieces together.
12:58 <dminuoso> dmwit: worked for me too, but I had a year of previous programming with immutable data and pure functions. :)
12:58 <thongpv3> I'm begining read Real World haskell, and completed 3 chapter, should I continue
12:58 <* dmwit> didn't
12:58 <dminuoso> thongpv3: RWH is very old and outdated.
12:58 <zincy> nitrix: The longwinded explanations didn't help test my understanding
12:58 <dmwit> My path was C -> C++ -> Python -> Gentle Intro. I had no prior experience with FP or immutability.
12:58 <dminuoso> dmwit: In the end learning is a highly individual thing.
12:58 <thongpv3> So I should pick Programming in Haskell.
12:59 <dminuoso> You should pick resources according to your needs and experience. :)
12:59 <dmwit> Can't argue with that.
12:59 <nitrix> You also have the option of learning by osmosis, doing a pet project and asking questions here :)
12:59 <pspace> i am doing C++ as main language and scala and now haskell as fun languages for side projects
12:59 <nitrix> We're a slow medium though.
12:59 <zincy> nitrix: My favourite way of learning
12:59 <dmwit> (Then again, the start of my path was "how do I create fractals? here's a book on how to do it in C", so recursion was natural and iteration the learned thing for me. =P)
13:00 <matsurago> thongpv3: have a look at that: https://www.amazon.com/Get-Programming-Haskell-Will-Kurt/dp/1617293768
13:00 <hc> hi all, how to set the content-length header in servant?
13:00 <thongpv3> Thankyou :)
13:01 alfa joined
13:01 <alfa> !list
13:01 <alp> hc, isn't it set automatically?
13:01 alfa left
13:01 fmixing joined
13:02 freeman42x]NixOS joined
13:03 freeman42x]NixOS joined
13:03 <hc> not when returning a wrapped lazy bytestring
13:03 <hc> anyway, i'll try a hack to fix an urgent bug
13:04 dogweather joined
13:04 codyw joined
13:04 <pspace> i am currently having a project where i am using Data.Fixed. does anyone know how to construct a Fixed from a string?
13:05 <nitrix> There's a Read instance, if that helps.
13:07 <nitrix> > read "42" :: Fixed E9
13:07 <lambdabot> error:
13:07 <lambdabot> Ambiguous occurrence ‘Fixed’
13:07 <lambdabot> It could refer to either ‘Data.Fixed.Fixed’,
13:08 <nitrix> > read "42" :: Data.Fixed E9
13:08 <lambdabot> error:
13:08 <lambdabot> Not in scope: type constructor or class ‘Data.Fixed’
13:08 <lambdabot> Perhaps you meant one of these:
13:08 <dmwit> > read "42" :: Data.Fixed.Fixed E9
13:08 <lambdabot> 42.000000000
13:08 <pspace> nitrix: thanks a lot
13:09 kapil___ joined
13:09 dbmikus joined
13:09 codesoup joined
13:10 hphuoc25 joined
13:10 plugin joined
13:11 <dminuoso> For the sake of docker caching Im thinking about keeping a "fake" cabal file that lists mosts of the dependencies. Is this sane?
13:11 <dmwit> Hm. Not sure I like this Read instance.
13:12 <nitrix> dmwit: "42.09" :: Fixed E1 truncates to "42.0"
13:12 <dmwit> ?let data B2
13:12 <lambdabot> Defined.
13:12 <dmwit> ?let instance HasResolution B2 where resolution _ = 4
13:12 <lambdabot> Defined.
13:12 <Geekingfrog> dminuoso: I believe that what stack does on the latest versions. There is a (big) images with lots of already compiled dependencies
13:12 tomboy64 joined
13:12 <dmwit> > (0.25 :: Data.Fixed.Fixed B2, read "0.25" :: Data.Fixed.Fixed B2)
13:12 <lambdabot> (0.3,0.0)
13:12 seangrove joined
13:13 <dmwit> nitrix: Explain this. It is not truncation, because 0.25 is exact.
13:13 <nitrix> . . .
13:13 <dmwit> I mean, I know why it behaves this way, because I can just look at the code and see. But I don't like it.
13:14 <nitrix> It just caught me.
13:14 <dminuoso> Geekingfrog: Mmm it looks a bit different from what Im doing
13:15 dhil joined
13:15 <dminuoso> Geekingfrog: Though I cant see what registry.gitlab.fpcomplete.com/fpco/default-build-image:1954 actually is.
13:15 <dminuoso> https://gist.github.com/dminuoso/6386dad71d04ec194552e047cdf89d49 this is what Im doing right now
13:16 enterprisey joined
13:16 <nitrix> dmwit: Shouldn't the resolution be powers of 10?
13:16 dogweather joined
13:17 <dmwit> Why?
13:17 <cocreature> dminuoso: I feel like a new-freeze file would be perfect for this but I’m not sure if cabal has a command for “install all packages in this freeze file”
13:18 forell joined
13:18 <dmwit> nitrix: (N.B. The Read instance even includes a comment saying they want to deal with e.g. `resolution _ = 128`, so I know the answer to that is no. I'm just playing Socrates here.)
13:19 ystael joined
13:19 zfnmxt joined
13:19 <dmwit> nitrix: And I will note that if they just used all the digits of precision instead of first truncating the String, then truncated the result, they would not have this problem.
13:20 <dmwit> > (2 / 10 :: Fixed B2, 25 / 100 :: Fixed B2)
13:20 <lambdabot> error:
13:20 <lambdabot> Ambiguous occurrence ‘Fixed’
13:20 <lambdabot> It could refer to either ‘Data.Fixed.Fixed’,
13:20 <dminuoso> cocreature: The problem is that when you add a single dependencies, that will suddenly bump up build time from 5 minutes to an hour.
13:20 <dmwit> > (2 / 10 :: Data.Fixed.Fixed B2, 25 / 100 :: Data.Fixed.Fixed B2)
13:20 <lambdabot> (0.0,0.3)
13:20 <dminuoso> So I want to kind of "prebuild" a list of expected dependencies in a previous layer, relying on new-build sharing compilations
13:20 <nitrix> dmwit: It's in base though. I feel like this should be fixed (no pun intended, okay maybe intended).
13:20 <dmwit> I agree, it seems simply broken.
13:21 <dmwit> And should be fixed.
13:22 zdenal joined
13:22 slomo joined
13:22 slomo joined
13:23 <cocreature> dminuoso: if you want non-shitty caching I wouldn’t rely on docker’s caching at all. just cache some external directory and mount that in your docker build
13:23 <cocreature> or use nix for caching
13:24 <dminuoso> cocreature: Not too keen to start learning nix because I've been investing a *lot* of hours on Haskell and other things - it's time we start getting productive so..
13:24 <dminuoso> For the moment anyway.
13:25 <dminuoso> cocreature: What would you cache for new-build exactly?
13:25 sw1nn joined
13:26 <cocreature> dminuoso: just cache ~/.cabal/store and mount that in your docker image
13:26 <cocreature> that’s pretty much how stack build --docker works as well
13:26 <dminuoso> Oh haha. It cant be that easy :)
13:26 <pspace> how to split my project into different files? should I do a file with all fatatypes and one with all instances? or one file for each datatype and its instances?
13:27 <pspace> what is best practice for splitting?
13:27 <cocreature> dminuoso: anything specific you’re worried about?
13:28 camsbury joined
13:28 xtreak joined
13:29 dan_f joined
13:29 ozataman joined
13:29 errst joined
13:30 dogweather joined
13:32 <maerwald> pspace: to avoid import cycles I often do a module with data types, but generally I would structure your files according to your architecture
13:32 <maerwald> if you don't know how to structure them, chances are good you haven't thought about architecture yet :P
13:33 <pspace> yeah i havent, it is just a small project
13:33 <pspace> it's my first haskell project
13:33 <maerwald> then just play around, don't care about "best practices". You'll probably run into one or another problem anyway
13:35 danthemyth joined
13:35 canaria joined
13:36 <ggVGc> the best practice is to get code that runs so you can see how shit it is and fix it!
13:36 <ggVGc> <-- professional software dev
13:36 <maerwald> yeah, prototyping 4tw
13:36 <ggVGc> google gets it, everything is a prototype
13:37 <maerwald> people talk about TDD and all that crap, but only prototyping works
13:37 <ggVGc> forever :(
13:37 <* ggVGc> is still prototype
13:37 <maerwald> yeah, occasionally we ship the prototype xD
13:37 <cocreature> ggVGc: take care that nobody accidentally throws you away and starts a new prototype!
13:37 <ggVGc> can I share the sad story of a few months ago when I prototyped a trading bot in haskell, fucked it up, and now it's in Elixir and running much better
13:37 <ggVGc> cocreature: I've got too much technical debt for that
13:38 <dminuoso> cocreature: Thanks. You just single handedly "unconvoluted" my CI setup. ;-)
13:38 <maerwald> I always prototype in python, then argue "this will be much cleaner in haskell" xD
13:38 <cocreature> dminuoso: heh, glad I was able to help :)
13:38 vurtz joined
13:39 cur8or joined
13:39 <ggVGc> my story wasn't completely accurate, the part that I thought haskell would be good for were actually really good in the haskell version. But the other IO-heavy stuff got completely messed up, partly because of me not completely understanding what I wanted, but also because haskell wasn't supporting the use case well. The current elixir version is really good at those parts, but actually a lot worse at the
13:39 <ggVGc> parts that were good in the haskell version..
13:39 iAmerikan joined
13:39 <ggVGc> so I'm actually about to integrate half of my old haskell version into this thing
13:39 <ggVGc> to get best of both worlds
13:39 <cocreature> IO-heavy stuff is the best part of Haskell!
13:39 curious_corn joined
13:40 <maerwald> maybe rewrite it in clojure, to get a 3rd opinion :>
13:40 <maerwald> cocreature: how so
13:40 codesoup joined
13:40 <ggVGc> cocreature: I really needed fault tolerance and a lot of async processes, and good interactive usage
13:40 <maerwald> exceptions are awful :/
13:40 <ggVGc> I got a lot of that for free in elixir
13:40 <zincy> hexagoxel: Thanks for mapAccumL it worked like a dream!
13:40 <ggVGc> but the defining of strategies and testing them were great in haskell
13:40 <ggVGc> and it's crap in the elixir version
13:40 <ggVGc> so...
13:40 <ggVGc> :(
13:41 <cocreature> fair enough, although at least the “lots of async processes” part is usually great in Haskell as well
13:41 <ggVGc> but it turns out that the fault tolerance part was more important
13:41 <ggVGc> but had to learn that though the first prototype
13:41 <maerwald> yeah, correctness is not always what you want, when it crashes your program :>
13:42 <ggVGc> the point of the story is, the only way for me to realise elixir was a better fit and why it was, was to build a useable thing in haskell first to see how it sucked
13:42 <ggVGc> so, fastest way to something you can use is always the best practice
13:42 <ggVGc> imo
13:42 <maerwald> for what? delivering features or writing good software
13:43 dogweather joined
13:43 <ggVGc> for creating any kind of software
13:43 <maerwald> well, I don't believe in gradual prototyping. I actually delete my prototypes and start from scratch
13:43 Azel joined
13:43 osa1 joined
13:43 <ggVGc> if you need to deliver a feature, it needs to built in the fastest way possible so you can see in which ways you misthought about the feature
13:43 <zincy> maerwald: haha
13:44 <maerwald> and for the non-prototype I don't care how fast I finish it
13:44 <ggVGc> maerwald: ah yeah, same. usually the 3rd version is where I start getting something that actually fulfills what I originally imagined
13:44 <ggVGc> I'm in my 3rd or 4th version of my sequencer software now, and it started being actually useful to me only about a year ago
13:44 <ggVGc> after doing it off and on for several years
13:44 <zincy> Does anyone else get stuck in the loop of finding the perfect solution and then three hours go by and you havent written a line of code and are no closer to a working feature
13:44 <zincy> its a bad habit i have
13:44 <maerwald> zincy: you fit percectly into haskell culture then
13:44 <maerwald> xD
13:45 <zincy> :x haha
13:45 <maerwald> maybe you should rather write Go to get rid of that habit
13:45 <ggVGc> zincy: sometimes, but not as much anymore, because I'm acutely aware of it and have some tactics to break free
13:45 <zincy> hahaha
13:45 <ggVGc> but it requires direct action
13:45 <maerwald> because in Go you cannot have a perfect solution anyway
13:45 <zincy> I actually have a friend which insists I do just that/1
13:45 <maerwald> it's crap either way, but it run nicely
13:45 <ggVGc> maerwald: it's nice, you never have to actually run your shit and deal with your problems. Just watch those nice compiler successes
13:45 <ggVGc> and your beautiful ADTs and type specs
13:45 <dminuoso> zincy: I find that whenever I fall into the pattern that I need to reapproach it. Sometimes I flip the "top-down/bottom-up" switch and that does the trick.
13:46 <zincy> dminuoso: what do you mean?
13:46 <ggVGc> zincy: one trick for me is to walk away a but, then come back as a user and just sit down and use my software, and instantly see "well, this just isn't possible to use" and then do the smallest thing to fix that specific annoyance
13:46 <ggVGc> and then I'm on a roll again
13:47 <dminuoso> zincy: So in software sometimes you have a top-down approach where you try to start writing from general code towards specific code.
13:47 tzemanovic joined
13:48 <zincy> ggVGc: Yes that too I need more breaks
13:48 <ggVGc> zincy: well, that's part of it. But also, switching perspective to being the user
13:48 <ggVGc> works well for me
13:48 tzemanovic joined
13:49 tzemanovic joined
13:50 tzemanovic joined
13:50 <zincy> ggVGc: you mean thinking about what end result the difference will make to the user?
13:50 ctom joined
13:50 drets joined
13:50 seangrove joined
13:50 <ggVGc> zincy: no, literally being the user
13:50 tzemanovic joined
13:50 <ggVGc> not thinking about what it would be like
13:51 <zincy> ggVGc: Oh so just use the app
13:51 twandy joined
13:51 <ggVGc> yeah, or whatever it is you're building
13:52 <ggVGc> you will either see 1. I can not actually use the app (I need to do the smallest thing, to get anything I can start up and use) or 2. Doing this thing is really awkward, why doesn't it work this way (make it work that way). or 3. This feature is just actually broken(bug) (fix the bug)
13:52 tsaka__ joined
13:52 <ggVGc> zincy: this usually instantly gets me on track
13:52 <ggVGc> but, I also only make software (personally) that I am the primary user of
13:52 <ggVGc> I find anything else really difficult
13:52 <ggVGc> at work it's not a problem since there's always well defined needs
13:52 pio_ joined
13:53 <ggVGc> e.g atm I'm writing backend for a tool, and the tool has certain needs, and either I fulfill them or I don't
13:53 crobbins joined
13:53 <ggVGc> but I think when you get stuck in that design loop, it's because you've lost the focus of what you're trying to build, and what you want to be able to do wit hit
13:53 <ggVGc> so you end up focusing on the wrong things
13:53 <ggVGc> well, this is my personal experience anyway
13:53 <zincy> ggVGc: That is simply the best way of allocating tasks for personal projects to yourself
13:54 twandy joined
13:55 <zincy> Thats the dream in the business world - the developer is the user
13:55 <zincy> I read in a book that John Carmack just built games he would enjoy playing
13:55 <ggVGc> yeah but that's never the actual case. I think that's fine though. You just need to find a way to stay focused on what you need to deliver, rather than how it should be implemented
13:55 <ggVGc> so your drive is to get it done as soon and as simple as possible
13:55 <ggVGc> rather then being stuck in building a golden house
13:56 <ggVGc> (that will turn out to be a rotten house anyway)
13:56 emilypi joined
13:56 <zincy> Yeah its an ideal case
13:56 Jeanne-Kamikaze joined
13:56 <zincy> Trading bot would have been fun though
13:56 <zincy> I would have thought elixir and haskell would be equally great for it
13:57 SpinTensor joined
13:57 <zincy> Maybe you just made your first prototype in haskell and then the second gen prototype happened to be in Elixir when you had a clearer idea of what you wanted
13:57 <ggVGc> they litereally each fill half of the story perfectly, I've found
13:57 <ggVGc> and now I've built both versions
13:57 <ggVGc> and will pick the good part from both and marry them
13:57 <ggVGc> is the plan anyway
13:58 <zincy> right tool for the job
13:58 <ggVGc> zincy: no the fault tolerance of erlang is really actively helping me not write a load of code I would have needed to write in the haskell version. And which is why the haskell version wasn't useful, since I didn't write that code
13:59 <ggVGc> but it's a lot harder and less safe making strategies for the elixir version, so I want to use what I wrote in haskell for that
13:59 <zincy> how does fault tolerance work in a trading bot
13:59 <ggVGc> well, for example, I have a websocket feed that dies 2-3 times per day. And it's a non-issue in the elixri version since it just crashes the process and restarts and reconnects
13:59 <zincy> As in what would be considered a fault?
13:59 <ggVGc> and I didn't have to do anything at all
13:59 <ggVGc> it's a bigger problem to handle in the haskell version
14:00 <zincy> What did you have to do in the haskell version?
14:00 saurabhnanda joined
14:00 <ggVGc> also, I sometimes get timeouts from the REST APIs, or hit rate limits, and that also ends up being a non-issue
14:00 <ggVGc> rather than something I have to deal with
14:00 arkaros joined
14:00 pfurla joined
14:00 <ggVGc> zincy: to achieve the same thing I'd have to make sure I handle any exception that might or might not happen. Or build a bad version of OTP with isolated threads sending messages to eachother
14:01 <ggVGc> at which point I'm just making bad erlang
14:01 <ggVGc> also, database access is a lot easier and light weight from elixir than haskell
14:01 <zincy> So is every trading bot for a given api running in a separate process
14:01 <zincy> and then when an exception is thrown in the elixir runtime the process just restarts?
14:02 ddellacosta joined
14:02 <ggVGc> there are many processes doing different things. One is fetching order books, one is validating orders being placed on exchanges, one is monitoring feeds, one is running strategies
14:02 <ggVGc> etc.
14:02 <ggVGc> and any one of them can crash and restart at any time
14:02 <ggVGc> and it's fine
14:02 zakora joined
14:02 <zincy> That is one complex program
14:02 <zincy> Did you finish it
14:03 <ggVGc> it's running live since about a month
14:03 <ggVGc> took me 2 days to write the basics of it
14:03 reactormonk joined
14:03 <ggVGc> OTP makes it easy, hence why the haskell version was bad
14:03 <zincy> Also where did you keep the state for how each strategy was performing , pnl etc?
14:05 <ggVGc> it's pretty simple. each strategy just has its state in a blob in a database, and gets pulled out and executed by a runner. If something fails the new state is not written to the DB (as long as no external actions have been executed)
14:05 <ggVGc> and each strategy is connected to a local account, which I can track what happens to
14:05 <ggVGc> it also prevents a strategy from running off and buying/selling too much
14:05 <zincy> How long have you been coding for? Im surprised you wrote that in two days
14:06 <ggVGc> I didn't write the whole thing in two days. Just the basic thing with fetching order book and runnign the strategies. There were some bugs and not great control, but the basics worked. Since then I've been working on it fairly actively the past month
14:06 <ggVGc> ah, also the account management part
14:06 <ggVGc> since those were the issues with the haskell version
14:07 <ggVGc> my point was, the hard problems in the haskell version took a few days to solve in elixir. But the strength of the haskell version (rigid definition of strategies) are missing in the elixir version now
14:07 mbwgh joined
14:08 keepLearning512 joined
14:08 <mbwgh> Is a first-order language one without higher-order functions and vice versa? Or is it more complicated than that??
14:08 <ggVGc> not sure I've heard the term first-order language before :(
14:09 <mbwgh> It show up all the time in the tagless-final lecture notes, for instance.
14:09 <mbwgh> Also in the context of "defunctionalization", where as I understand it, you turn CPS-style back into first-order style.
14:10 <mbwgh> As described in the last chapter of Hutton's book, where they implement a compiler
14:11 knupfer joined
14:11 AndreasPK_ joined
14:11 <zincy> :t %=
14:11 <lambdabot> error: parse error on input ‘%=’
14:11 <zincy> :t (%=)
14:11 <lambdabot> MonadState s m => ASetter s s a b -> (a -> b) -> m ()
14:12 <mbwgh> I'm pretty sure lens is a higher-order language
14:12 <zincy> :t ASetter
14:12 <lambdabot> error:
14:12 <lambdabot> • Data constructor not in scope: ASetter
14:12 <lambdabot> • Perhaps you meant one of these:
14:12 <mbwgh> :i ASetter
14:12 <mbwgh> :(
14:12 <cocreature> mbwgh: I’m not sure first-order language is really a well-established term but my interpretation would be the same as yours
14:12 jeltsch joined
14:13 <zincy> What is the ASetter s s a b
14:13 dogweather joined
14:13 <ggVGc> it does sound like a language that can not represent it's own pieces in a first-order way. e.g for example not having functions as first class citizens
14:13 <ggVGc> but this is quite a fair bit of speculation form me
14:13 <mbwgh> cocreature: Would you regard C a higher-order language then? You can take function pointers as arguments and return them. But you can't create functions on the fly or easily capture an environment without things quickly becoming hairy
14:14 <ggVGc> with that definition I owuld definitely consider C first order
14:14 adkron joined
14:14 <ggVGc> a function pointer is not a function
14:14 <AWizzArd> I have a function eval :: (Show a) => Environment a -> Term -> Either String Term and later want to call it: prog1' = eval emptyEnv prog1 but GHC complains that an »Ambiguous type variable ‘a0’ arising from a use of ‘eval’ prevents the constraint ‘(Show a0)’ from being solved.«
14:14 <ggVGc> you can't, for exampole, in a reasonable way partially apply it
14:15 <cocreature> zincy: it’s the type of things that can act as setters, Lens, Prism, … can all be specialized to that type
14:15 <AWizzArd> What other type than prog1' :: Either String Term should I use to make clear that Showing is possible?
14:15 <ggVGc> I think Lens types could be a uni course in itself
14:15 <ggVGc> or maybe a year
14:15 <cocreature> mbwgh: probably not but without agreeing on some formal definition I don’t think it makes sense to debate whether it applies to C
14:15 keepLearning512 joined
14:15 <zincy> ggVGc: haha
14:16 <mbwgh> Ok I guess I'll go with first-order => no HOFs until it blows up in my face
14:16 <zincy> I need to get some motivation to learn Lens
14:16 canaria joined
14:17 <ggVGc> well, I'd argue the type specs isn't one
14:17 <mbwgh> zincy: Try to update a deeply nested record without them
14:17 <cocreature> zincy: are you familiar with the Traversable typeclass?
14:18 <ggVGc> zincy: I think Lens allows you to think about your data in new intersting ways, and gives you kind of structural typing, so you can write functions for "values that have x and y" for example
14:18 <ggVGc> that was my main original motivation to get into it
14:18 <ggVGc> also, Lens allows you to implement fairly nice DSL with very little effort
14:19 eliasr joined
14:19 <ggVGc> if that's a good or bad thing is up to you :)
14:19 jan-sipr joined
14:20 <quicksilver> zincy: you'll find motivation soon enough.
14:20 <kuribas> zincy: how do you increment each part of a tuple?
14:20 <quicksilver> foo { bar = bar foo { baz = baz bar foo + 1 } } is enough motivation for many
14:20 <quicksilver> but thre are penty of other convincing places
14:21 <kuribas> > over both (+1) (3, 2) -- zincy
14:21 <lambdabot> (4,3)
14:21 <ggVGc> quicksilver: what about "feeling clever"?
14:21 <ggVGc> that's a pretty big one around haskell I think :)
14:21 Versalife joined
14:21 <mbwgh> zincy: I would strongly recommend having a look at the microlens haddocks, and probably also the Wikibooks article. Other than that, it is perfectly fine to use lens as "getters and setters" when starting out. You don't need to know about Prisms, Isos, or the classy stuff in order to get stuff done with them.
14:22 <zincy> cocreature: Yeah traversable just has the traverse function as a required function right
14:22 <zincy> :t traverse
14:22 <lambdabot> (Applicative f, Traversable t) => (a -> f b) -> t a -> f (t b)
14:23 <zincy> feeling clever is a good reason to do anything
14:23 <mbwgh> zincy: Also, there is a library that clamis to provide comprehensible error messages: https://github.com/mrkgnao/silica It isn't overly discoverable, since it isn't on hackage.
14:23 <zincy> mbwgh: thanks sounds good
14:24 <zincy> should I look at microlens instead of simple-lens
14:26 <mbwgh> zincy: I think this is one of the shortest lens guides: https://guide.aelve.com/haskell/lenses-sth6l9jl
14:27 <mbwgh> zincy: I personally have only really used `lens` itself, and used the microlens haddocks as some sort of tutorial. But the haddocks of lens have improved significantly as well.
14:27 <zincy> Can you imagine onboarding someone new to haskell to lensified codebase :)
14:27 camsbury joined
14:28 <zincy> :t (.).(.)
14:28 <lambdabot> (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
14:28 <glguy> zincy: Yeah, I've done that
14:28 <zincy> how did it go?
14:28 <cocreature> zincy: exactly, lens’ Traversal type is just a generalization of the "traverse" function
14:28 <glguy> fine
14:29 <cocreature> :i Traversal
14:29 <cocreature> % :i Traversal
14:29 <yahb> cocreature: type role ReifiedTraversal representational nominal representational nominal; newtype ReifiedTraversal s t a b = Traversal {...}; -- Defined in `Control.Lens.Reified'; type Traversal s t a b = forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t -- Defined in `Control.Lens.Type'
14:29 <cocreature> well that looks horrible
14:29 <zincy> glguy: how long did it take for them to be productive?
14:29 <cocreature> but if you look at the end you see the interesting part "type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s f t"
14:29 <zfnmxt> I need to generate register labels that are unique, i.e. each new label is different from all previous labels. Should I just do this by incrementing a counter or is there a nice library that provides that sort of fucntionality?
14:30 <cocreature> Lens is then just a Traversal that always targets exactly one element. this also lets you "view" that element in addition to modifying all elements targetted by the Traversal
14:30 dogweather joined
14:31 <maerwald> does anyone have a working deoplete configuration?
14:31 <maerwald> the documentation is really bad
14:31 <glguy> zincy: They were able to be productive right away and then of course they got more comfortable
14:32 arkaros joined
14:32 <zincy> glguy: So from no haskell experience they hit the ground running in a haskell codebase?
14:33 <zincy> I need some context did they have 5 years of exp in another ML lang
14:33 codesoup joined
14:35 <glguy> I think that Haskell was his first language in that family, but he was an experienced programmer
14:36 <zincy> Ah ok
14:36 <glguy> but at work we've brought a number of people onto Haskell projects who needed to learn it
14:36 language_agnosti joined
14:36 <zincy> glguy: Where do you work
14:37 <* hackage> layered-state 1.1.4 - Control structure similar to Control.Monad.State, allowing multiple nested states, distinguishable by provided phantom types. http://hackage.haskell.org/package/layered-state-1.1.4 (danilo2)
14:43 jedws joined
14:44 mkoenig joined
14:45 mizu_no_oto joined
14:47 crobbins joined
14:48 dogweather joined
14:49 <zincy> How do I use %= to set something on a list of lensified values?
14:49 amirpro joined
14:50 <maerwald> deoplete is really impossible to get working, I'm confused about the positive reviews
14:50 <zincy> (username %= "") <$> players :: [Player]
14:50 <cocreature> zincy: are you in State? (%=) is only the stateful version of (%~)
14:50 <zincy> not in State
14:50 <cocreature> then the first step is to use (%~) instead of (%=) :)
14:51 alx741 joined
14:51 <zincy> :)
14:51 <zincy> (pockets %~ []) <$> players :: [Player]
14:51 <cocreature> > [(1,2), (2,3)] & traverse . _1 %~ (+1)
14:52 <lambdabot> [(2,2),(3,3)]
14:52 <cocreature> is that what you’re looking for?
14:52 HarveyPwca joined
14:52 kderme joined
14:52 <zincy> does traverse come from Lens
14:52 <zincy> or traversable
14:52 HarveyPwca joined
14:52 <cocreature> no it’s the traverse from Traversable
14:53 <cocreature> as I mentioned before, lens’ Traversal type is just a generalization of the "traverse" function
14:53 <zincy> what does & do
14:53 <cocreature> (&) is flipped function application, it’s in base
14:53 <cocreature> :t (&)
14:53 <lambdabot> a -> (a -> b) -> b
14:54 mreznik joined
14:55 mreznik left
14:55 Linter joined
14:56 <zincy> thanks!
14:56 <zincy> Traverse is just mapping with effects right?
14:56 knupfer joined
14:56 dogweather joined
14:57 jkachmar joined
14:57 hphuoc25 joined
14:58 <nitrix> zincy: That's a good intuition. There are laws associated to it though.
14:59 <zincy> :)
14:59 <zincy> Oh
14:59 <zincy> :t %~
14:59 <lambdabot> error: parse error on input ‘%~’
14:59 <cocreature> you need parenthesis around the operator
14:59 language_agnosti joined
14:59 mreznik joined
15:00 conal_ joined
15:00 <zincy> :t (%~)
15:00 <lambdabot> ASetter s t a b -> (a -> b) -> s -> t
15:00 HarveyPwca joined
15:00 ixxie joined
15:00 <zincy> hmm let players' = (players :: [Player]) & traverse . (pockets %~ ([] :: [Card]))
15:00 <cocreature> zincy: I would recommend looking at the simplified type signatures in the lens’ docs rather than the ones that :t spits out
15:01 <nitrix> (%~) :: Setter a a' b b' -> (b -> b') -> a -> a'
15:01 <zincy> ok will do
15:01 dhil joined
15:01 <zincy> let players' = (players :: [Player]) & traverse . (pockets %~ ([] :: [Card]))
15:02 <cocreature> your parenthesis are wrong
15:02 <zincy> • Couldn't match type ‘Player’ with ‘a -> f b’ Expected type: Player -> a -> f b Actual type: Player -> Player • Possible cause: ‘(%~)’ is applied to too many arguments In the second argument of ‘(.)’, namely ‘(pockets %~ ([] :: [Card]))’ In the second argument of ‘(&)’, namely ‘traverse . (pockets %~ ([] :: [Card]))’ In the expression: (play
15:02 <cocreature> and [] is not a function
15:02 <zincy> what about const
15:02 <zincy> :t const
15:02 <lambdabot> a -> b -> a
15:02 <cocreature> also please use a pastebin for multiline error messages
15:03 <cocreature> that would work or you can use .~ instead of %~
15:03 DSM joined
15:03 <zincy> https://lpaste.net/5971647710028103680
15:04 <cocreature> start by fixing the errors I told you about and then show us the new errors (if any) :)
15:04 tomboy64 joined
15:04 <zincy> I did what you said and ... it works!
15:04 <zincy> let players' = (players :: [Player]) & traverse . pockets .~ ([] :: [Card])
15:04 <cocreature> even better :)
15:05 <zincy> :D
15:05 <zincy> Thank you
15:05 <nitrix> zincy: (%~) has the lens on the left (that'll focus onto some parts of your Traversable) and a transformation function on the right (to be applied).
15:05 <nitrix> .~ works :)
15:05 <cocreature> just to be clear, the parenthesis are around (traverse . pockets)
15:05 thc202 joined
15:05 Destol joined
15:05 <zincy> so %~ takes a function and .~ just sets a value
15:05 ixxie_ joined
15:06 <cocreature> .~ is pretty much %~ combined with const
15:06 <zincy> Makes sense
15:06 <zincy> :)
15:06 <zincy> traverse . lensThing .~ someValue
15:06 <zincy> is lensThing a lens
15:06 amar_ joined
15:07 <cocreature> that’s a bit hard to say without seeing its definition
15:08 <Taneb> zincy: a lens would certainly fit there
15:08 amar_ joined
15:08 dogweather joined
15:09 <zincy> Are lens operators such as (%=) and (.~) just functions which take lens?
15:09 <zincy> And return the complete structure without zooming in
15:10 lumm joined
15:10 <zincy> Whereas ^. would get you the zoomed in structure?
15:11 <fr33domlover> Btw, Wikibooks has an amazing lens tutorial
15:12 <zincy> thanks will look
15:13 <zincy> this one? https://en.wikibooks.org/wiki/Haskell/Lenses_and_functional_references
15:13 <fr33domlover> zincy, yeah
15:13 seanparsons joined
15:14 jedws joined
15:15 codesoup joined
15:16 <drets> Is there a way to return value of my custom data type from http://hackage.haskell.org/package/esqueleto-2.5.3/docs/Database-Esqueleto.html#v:select ? Should I implement instance of SqlSelect? But it's internal class :|
15:16 <geekosaur> generally you have to marshal and unmarshal from what the database supports
15:18 <* hackage> semilattices - Semilattices http://hackage.haskell.org/package/semilattices- (robrix)
15:18 <drets> yeah, and my question is how... will try to create example.
15:18 Solonarv joined
15:21 Iri joined
15:22 wildlander joined
15:22 <fr33domlover> drets, look at the function signatures, there should be a typeclass for everything you can return. Maybe it also uses classes from persistent. Btw check out the Selda library :)
15:23 <fr33domlover> gtg bbl o/
15:24 saurabhnanda joined
15:25 <glguy> zincy: galois.com
15:26 <AWizzArd> Some users may expect that when my type implements Show that they can call read on the result of calling show. Is there an alternative to the Show TC that I can use for any String representation that I want?
15:26 howdoi joined
15:26 ixxie joined
15:27 <geekosaur> not a standard one, nbecause everyoen has different expectations in that area
15:27 <glguy> AWizzArd: No. If you need some application specific formats you should make a new typeclass for that (assuming a typeclass is needed at all)
15:27 <geekosaur> there are prettyprinter libraries that can help you build your own
15:27 <saurabhnanda> Been scratching my head over Perstitent's types for quite some time now. Which function concretizes the `BaseBackend backend` constraint finally? https://gist.github.com/saurabhnanda/6d10581503ae877e61de5edef3574538
15:29 falafel joined
15:29 <AWizzArd> glguy: is there a way to marry ghci’s repl with my own mirrored Show TC?
15:29 urodna joined
15:30 <zincy> glguy: Fun company to work for?
15:30 <glguy> yup :)
15:31 <zincy> Ok lens lead to nice concise code
15:31 dogweather joined
15:31 <glguy> AWizzArd: Not that I'm aware of
15:31 <geekosaur> AWizzArd, https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/flags.html#ghci-interactive-print
15:31 DSM joined
15:31 ixxie_ joined
15:32 <geekosaur> beh, thta's broken, they lost the docs, it points to itself :(
15:32 <suppi> https://teh.id.au/posts/2017/02/13/interactive-print/index.html
15:32 <geekosaur> https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html#using-a-custom-interactive-printing-function
15:33 <AWizzArd> Oho! :-)
15:33 <glguy> Ah, now I'm aware of one :)
15:34 <* hackage> hexpat-lens 0.1.7 - Lenses for Hexpat. http://hackage.haskell.org/package/hexpat-lens-0.1.7 (OliverCharles)
15:34 canaria joined
15:34 curious_corn joined
15:35 <* hackage> semilattices - Semilattices http://hackage.haskell.org/package/semilattices- (robrix)
15:35 amiri joined
15:35 <dminuoso> zincy: For me at least, simply changing the direction in which I code tends sometimes stop sme worrying about "getting it right". For me personally it works :0
15:36 <drets> fr33domlover, I think it's PersistField, thanks.
15:36 brandly joined
15:36 <* hackage> lawful - Assert the lawfulness of your typeclass instances. http://hackage.haskell.org/package/lawful- (mnoonan)
15:38 <zincy> dminuoso: Not sure I follow
15:39 danthemyth joined
15:39 trcc joined
15:39 dsh joined
15:40 johnvonneumann joined
15:41 <dminuoso> zincy: That was regarding your earlier question how to defeat certain cyclic behavior patterns. :P
15:42 GodotMisogi joined
15:42 xkapastel joined
15:42 <zincy> dminuoso: Yeah I know. I didn't follow what you meant by "direction"
15:43 <zincy> :)
15:43 <dminuoso> zincy: Like I said. Top-down vs bottom-up
15:43 <zincy> ah yes I remember now
15:43 texasmynsted joined
15:44 dogweather joined
15:45 codesoup joined
15:48 amar_ joined
15:49 slomo joined
15:49 ph88 joined
15:50 jedws joined
15:51 ixxie joined
15:52 slomo joined
15:53 whaletechno joined
15:55 Luke joined
15:55 tabaqui1 joined
15:56 ixxie_ joined
15:58 nuncanada joined
16:00 plugin_ joined
16:00 Unhammer joined
16:02 ixxie joined
16:02 raichoo joined
16:04 knupfer joined
16:04 Kacia joined
16:04 skeet70 joined
16:06 woodson joined
16:07 ixxie joined
16:08 djbeau joined
16:09 mizu_no_oto joined
16:11 dogweather joined
16:12 ixxie_ joined
16:13 altjsus joined
16:16 codesoup joined
16:17 progfun joined
16:17 ixxie joined
16:17 troido joined
16:21 oisdk joined
16:22 ozzymcduff joined
16:22 Linter joined
16:23 edmundnoble joined
16:23 HarveyPwca joined
16:24 dogweather joined
16:24 tv joined
16:24 DSM joined
16:27 ixxie joined
16:27 Immune joined
16:27 Immune left
16:27 nuncanada2 joined
16:29 fmixing joined
16:30 raichoo_ joined
16:30 tabaqui1 joined
16:31 lambda-11235 joined
16:33 ixxie_ joined
16:34 jekor joined
16:35 perspectival joined
16:36 mkoenig_ joined
16:37 dogweather joined
16:37 vurtz joined
16:37 newsham joined
16:38 remyhr joined
16:38 ixxie joined
16:38 diwo joined
16:39 reygoch joined
16:40 <sm> https://www.codingame.com/contests/code-of-kutulu might be fun for haskellers
16:40 <sm> starting today
16:42 kritzefitz joined
16:42 raichoo_ joined
16:43 <reygoch> So, I have this : forall m a e x. (Functor m, a ~ (x -> ExceptT e m x), ...) => ...
16:44 <reygoch> but I'm getting the message that m occurs more often in the constraint than in the instance head
16:45 <reygoch> is it not possible to put a constraint on the m in this case?
16:46 <cocreature> reygoch: can you show us the full error message?
16:46 <reygoch> sure, just a sec
16:46 codesoup joined
16:47 raichoo joined
16:47 <reygoch> https://lpaste.net/2201506163260915712
16:47 <reygoch> there :)
16:48 Gurkenglas joined
16:49 <reygoch> cocreature: I'm trying to make a function which can take infinite number of arguments, but since my arguments are parametrized it get's complicated
16:49 <zfnmxt> I'm sort of finding myself in a situation where I have like 5 different modules all involving types with StateT monads. I want to combine everything into one "big" StateT monad. Is there a nice way to do that?
16:49 <cocreature> reygoch: GHC already tells you how to fix this: enable UndecidableInstances
16:50 <reygoch> Yes, but I'd like to avoid that.
16:50 <cocreature> why?
16:50 <cocreature> if you are doing anything fancy with typeclasses, you will pretty much always find yourself having to enable UndecidableInstances
16:50 <reygoch> code will get a bit more complicated onward and I think undecideable will bite me in the ass
16:51 <reygoch> here is example of what I'm trying to do: https://lpaste.net/4822520422480216064
16:51 <reygoch> I want to have function which takes infinite number of arguments
16:51 <reygoch> but my arguments are heavily parametrized
16:51 <cocreature> GHC’s termination checker for instances is pretty dumb, so you have UndecidableInstances to turn it off
16:51 tsaka__ joined
16:51 <cocreature> at worst that will give you an infinite loop at compile time (although in practise, GHC has some (configurable) limit after which it gives up iirc)
16:52 <reygoch> but I'm getting the feeling that I'm dumb and there is a better way to go about this :D
16:52 <reygoch> ok, I'll go with undecideable for the time being
16:52 <cocreature> are all your arguments of type x -> ExceptT e m x?
16:52 <reygoch> thanks
16:52 <reygoch> no
16:52 <reygoch> some are of type Validator i m e
16:52 Falkaofalk joined
16:52 <cocreature> that seems to be the return value not the argument?
16:53 <reygoch> It can be argument as well
16:53 <reygoch> I'm trying to do the same thing printf does
16:53 karlguy_ joined
16:53 <reygoch> taking in infinite number of varying arguments
16:54 Falkaofalk joined
16:54 <cocreature> your instances doesn’t really seem to allow for that no? you have a single instance for (a -> o) that forces a to be (x -> ExceptT e m x) and o to be Validator i m e
16:55 <reygoch> this is just one branch of the recursion
16:55 <cocreature> hm hard to say then if things will fit together correctly :)
16:55 <reygoch> yes :D
16:55 <reygoch> well, I'll make them fit! XD
16:56 <cocreature> but you can’t make two instances for Checker s (a -> o)
16:56 DSM joined
16:56 <reygoch> oooo...
16:56 <reygoch> damn,
16:56 <reygoch> this was my second approach actually
16:56 <cocreature> so I think you probably want one for Checker s (a -> Validator i m e) and then another one for Checker s (a -> o) and Overlapping instances
16:56 alex`` joined
16:57 <reygoch> damn, I think I'll have to look for another approach
16:57 <cocreature> or even one for Checker s (Validator i m e) and for Checker s (a -> o) and no overlapping instances
16:57 fmixing joined
16:57 <cocreature> either way, this might all not apply to your situation but it’s really impossible to tell without having more context :)
16:58 <reygoch> well... I'll get back to work and hopefully report back with a nice and simple validation library :)
16:58 <reygoch> thanks for advice
16:58 davr0s joined
16:58 <cocreature> have fun :)
16:58 <reygoch> sure will
17:04 refold joined
17:05 progfun joined
17:06 <AWizzArd> I have a function foo :: a -> (forall b. b -> b -> Bool) -> Bar and want to know how I can add an Eq constraint to the `b` in the Rank2 fn.
17:06 <AWizzArd> Where does this syntactically go?
17:07 <int-e> (forall b. Eq b => b -> b -> Bool)
17:07 <glguy> AWizzArd: You can just write that: foo :: Eq b => a -> b -> b -> Bool, and it will be the same
17:07 <glguy> ohhh, sorry, linewrapping
17:07 <glguy> I missed the -> Bar :)
17:08 <AWizzArd> Oki. I tried 2-3 locations for the constraint but didn’t think of that one. Now it works, thx!
17:09 chat__ joined
17:09 danza joined
17:10 enterprisey joined
17:10 psychicist__ joined
17:12 raichoo_ joined
17:13 dogweather joined
17:14 <zfnmxt> I made a small module to that's basically a counter: https://github.com/zfnmxt/TigerHaskell/blob/master/compiler/src/Temp.hs and I need to integrate it into my CheckerState monad (line 28) https://github.com/zfnmxt/TigerHaskell/blob/master/compiler/src/Semant.hs . I'm not really sure how to do that. Do I just make larger monad transformer stack? Seems kind of ugly.
17:16 fishythefish joined
17:19 plugin joined
17:20 <[exa]> zfnmxt: what about just type Env = (VEnv,TEnv,Temp) ?
17:20 <zfnmxt> Well, I thought of that too. Where Temp :: Int, right?
17:20 <[exa]> zfnmxt: btw extending is easier (and code cleaner) if you use records with named fields instead of long tuples
17:20 <[exa]> (where 2 is already long)
17:21 <zfnmxt> I generally use records, but I guess I should be more consistent.
17:21 <[exa]> zfnmxt: I thought that you have defined Temp (not int)
17:22 <zfnmxt> Oh, right.
17:22 <zfnmxt> But, somehow I dislike that because I like the modular nature of having things like mkTemp, etc. I don't know if that make sense.
17:22 <* hackage> pinch - An alternative implementation of Thrift for Haskell. http://hackage.haskell.org/package/pinch- (abhinav)
17:22 <zfnmxt> It seems like by changing Env I'm sort of "forcing" the Temp into the Env in a somewhat non-modular way. But maybe that's just my lack of understanding.
17:23 <[exa]> zfnmxt: why would mkTemp stop working?
17:23 t7 joined
17:23 <zfnmxt> I wouldn't use it, would I?
17:23 <zfnmxt> If I have Temp in the Env I'd have to manually update Temp instead of using mkTemp, right?
17:23 <[exa]> yeah in this case it will stop working because it requires the state to be exactly Temp, but you can easily make it work on the extended state
17:24 <zfnmxt> Right, but then I'm rewriting mkTemp
17:24 <zfnmxt> Isn't there a nice way to combine the CheckerState monad in Semant.hs with the GenTemp monad?
17:25 <[exa]> hmm... what about a bit of overloading?
17:25 <zfnmxt> What do you mean?
17:25 <zfnmxt> Sorry about my confusion. I still find monad transformers difficult to understand/reason about :)
17:25 <[exa]> did you try working with MTL?
17:26 t8 joined
17:26 <[exa]> the idea is that you make a class that is called e.g. "HasTemp" for monads that provide Temp setting/getting
17:26 <[exa]> and using a bit of instances you can easily derive the HasTemp for whole monad stacks
17:27 mpbd2 joined
17:27 amar_ joined
17:27 <[exa]> which prevents most of manual lifting in the code and makes the thing quite readable
17:27 <zfnmxt> Hm, I see.
17:28 <zfnmxt> Do you know of any examples of using typeclasses in that way?
17:28 <zfnmxt> Just so I have a concrete reference
17:28 <[exa]> I guess this can be a good starting point https://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Monad-State-Lazy.html#g:4
17:29 Luke joined
17:29 ozataman joined
17:30 <[exa]> 'MonadState s m' means that there's a (StateT s) hidden somewhere in the stack, and get/put will work as if it was not stacked
17:31 <glguy> and it doesn't have to be an actual StateT, just any type that implements the interface
17:31 Soundquelle joined
17:31 <[exa]> oh the examples there aren't very explanatory regarding the actual typeclass usage
17:31 <glguy> so if you're doing this style for your project you might have a single type tha implements all the interfaces needed by various components
17:31 <zfnmxt> Heh, right. I was confused about the examples. :)
17:31 canaria joined
17:32 <reygoch> I'm having trouble with writing this class: https://lpaste.net/1904271663051046912
17:32 <reygoch> Is it possible to do something like this?
17:32 dogweather joined
17:32 <zfnmxt> glguy: And that type would be a MonadState <something>?
17:32 <[exa]> there should be a nice reading about MTL somewhere...
17:33 <glguy> zfnmxt: Yeah, as long as there's an instance that has the expected behavior it's fine
17:33 <zfnmxt> Is it easy to add new components like that?
17:33 Hafydd joined
17:34 fizbin joined
17:34 <zfnmxt> The issue I'm having here is that I didn't realize I needed a counter until after I wrote my typechecker :)
17:34 <[exa]> zfnmxt: this is good I guess: https://blog.jle.im/entry/mtl-is-not-a-monad-transformer-library.html
17:34 <glguy> zfnmxt: It's easier if you make sure that your main type is fairly abstract and that nothing is depending on its implementation, just the operations you've defined on that type
17:34 <[exa]> zfnmxt: you will want to implement something like MonadTemp and MonadEnv
17:34 raichoo joined
17:35 <glguy> then you'll be free to change it around to support the new functionality like having a counter without breaking everything else
17:35 <zfnmxt> I see.
17:35 <reygoch> So, is it impossible to bind scoped variables in class instance?
17:35 <zfnmxt> Thanks [exa] , I'll read that :)
17:35 <zfnmxt> I guess this also comes with experience (which I don't have) :)
17:35 <glguy> reygoch: the instance variables are already scoped
17:36 <reygoch> but I I have method with variables that aren't mentioned in the class definition?
17:36 <reygoch> like this : https://lpaste.net/1904271663051046912
17:36 <glguy> that's fine, don't forall the variables that are already in scope
17:37 <cocreature> i.e. don’t forall anything here :)
17:37 <reygoch> but it doesn't work either way
17:37 <cocreature> what’s the error once you remove the forall?
17:38 <reygoch> same
17:38 <reygoch> but now that I think of it
17:38 <reygoch> maybe I should add type signature to my definition
17:38 <reygoch> for `validator` function
17:39 fizbin joined
17:39 <glguy> reygoch: The correct type signature is: mkarg :: (i -> x) -> (x -> ExceptT e m x) -> Validator i' m' e'
17:40 bugrum joined
17:40 <glguy> You were trying to relate the univerally quantified type variables i m e in mkarg with the variables in the instance head
17:41 <glguy> Which means your class is wrong, not your instance, most likely
17:41 <reygoch> So how do I make i' ~ i, m' ~ m, and e' ~ e ?
17:41 <zfnmxt> So for my specific problem, it seems like I could actually essentially solve it just by swithing Env to a record type. The argument for MonadState is to make things not break if I change my current usage of StateT, right?
17:42 <[exa]> zfnmxt: this is even better reading I guess https://wiki.haskell.org/Monad_Transformers_Tutorial
17:42 <[exa]> zfnmxt: yes, if you want it working, go with a record type. If you somehow depend on the Temp State monad to be completely independent on the rest of the thing, you should probably go with the typeclasses
17:42 <glguy> reygoch: You probably just don't need a class
17:43 lumm joined
17:43 <zfnmxt> [exa]: Where "go with typeclasses" <--> "use MonadState", right?
17:44 <glguy> zfnmxt: You shouln't rely on literal MonadState, that's just an example of the approach
17:44 <glguy> You should make a class specific to the operations your counter functionality needs
17:44 fizbin1 joined
17:44 <zfnmxt> And then make CheckerState an instance of that class?
17:44 Folkol joined
17:44 <glguy> yeah
17:45 <zfnmxt> Okay. I'll do that, if only to learn about that approach :)
17:45 dxld joined
17:45 <[exa]> :]
17:45 <zfnmxt> Thanks for the help!
17:47 MarcelineVQ joined
17:49 agander joined
17:49 dogweather joined
17:54 kritzefitz joined
17:56 codesoup joined
17:56 conal_ joined
17:57 sw1nn_ joined
17:57 emilypi joined
17:58 zero_byte joined
18:00 c_my_nick joined
18:00 raichoo_ joined
18:00 Durbley joined
18:01 jez_ joined
18:02 jez_ joined
18:02 dogweather joined
18:02 conal_ joined
18:03 <c_my_nick> why is cabal new-build ignoring my freeze file? it has Cabal == in it, but it wants to install Cabal- (and runs out of memory when it tries)
18:03 <c_my_nick> the dependencies on this project havent changed since the last time i ran cabal new-freeze
18:06 <sclv> c_my_nick: have you tried using an index-state timestamp? https://cabal.readthedocs.io/en/latest/nix-local-build.html?highlight=freeze#cfg-field-index-state
18:07 <sclv> As i mentioned on the other channel, I think that the freeze constraint isn't applying to a build-tool dependency perhaps
18:07 asdfjkljkl joined
18:07 <sclv> i hope/suspect that the index-state would work more uniformly
18:08 <c_my_nick> i dont even know what value i would use for that
18:10 <zfnmxt> At the end of the first section in this post: https://ocharles.org.uk/blog/posts/2014-12-04-record-wildcards.html he talks about "applicative syntax"--what's that?
18:10 path[l] joined
18:10 replay joined
18:12 raichoo joined
18:12 <c_my_nick> zfnmxt, i assume he is referring to the use of the <$> and <*> functions, instead of do notation: undefined <$> o .: "name" <*> o .: "position" ... etc.
18:13 remyhr joined
18:13 <sclv> c_my_nick: pick a timestamp from when you had a successful build
18:13 <sclv> like e.g. the timestamp from when your new-freeze was?
18:13 lortabac_ joined
18:13 ozzymcduff joined
18:14 <zfnmxt> c_my_nick: Ah, right. Thanks.
18:16 remyhr_ joined
18:17 raichoo_ joined
18:18 acertain joined
18:19 paidnode joined
18:20 enterprisey joined
18:20 <c_my_nick> zfnmxt, i guess that works (added a couple days to the last modified date of the freeze file), but it wants to update a bunch of other packages too.
18:20 <zfnmxt> c_my_nick: wrong person :)
18:20 <c_my_nick> whoops ><
18:22 connrs joined
18:22 mkoenig joined
18:22 raichoo joined
18:24 dogweather joined
18:24 nitrix joined
18:25 nitrix joined
18:28 Linter joined
18:30 agander joined
18:31 elfets joined
18:32 danza joined
18:33 Linter joined
18:34 kefin_ joined
18:35 canaria joined
18:35 deeplearner joined
18:36 raichoo_ joined
18:36 dogweather joined
18:36 <zfnmxt> [exa]:
18:36 <zfnmxt> Oops.
18:37 <zfnmxt> [exa]: So I got this far: https://github.com/zfnmxt/TigerHaskell/blob/master/compiler/src/Semant.hs
18:37 <zfnmxt> I think that's okay, but it just augments the Env. I don't really see how to do it without doing that (i.e. using the GenTemp monad)
18:37 <zfnmxt> (See line 37)
18:37 emilypi joined
18:40 <[exa]> oh okay, that's an approach that mixes both :]
18:40 conal_ joined
18:41 <zfnmxt> Yeah, I guess so :D
18:41 <zfnmxt> But I'd like to do it with just the GenTemp monad, to make sure I understand
18:42 nickolay_ joined
18:42 <[exa]> the total pure MTL way would be this: 1] TempT that is built upon StateT, with accompanying class HasTemp 2] CheckerStateT with HasCheckerState 3] (the fun part) inductive instances that say "any monad transformer that contains a CheckerState is also in HasCheckerState
18:43 emilypi joined
18:45 <zfnmxt> [exa]: Okay, let me play around and see if I can get something like that. Thanks!
18:45 <[exa]> wild unchecked guess about the code that might be completely wrong because I don't have ghci handy: instance (MonadTrans mo, HasTemp mi) => HasTemp (mo mi) where {mkTemp = lift mkTemp}
18:45 karlguy_ joined
18:45 tsoernes joined
18:46 ijks joined
18:46 altjsus joined
18:48 albertus1 joined
18:48 slack1256 joined
18:49 <[exa]> which way you can have a monad stack that looks roughly like: TempT (CheckerStateT (Either Error))
18:49 DSM joined
18:50 canaria joined
18:54 Tops2 joined
18:54 Kundry_Wag joined
18:54 crobbins joined
18:55 zachk joined
18:55 zachk joined
18:57 danza joined
18:58 acarrico joined
19:00 oisdk joined
19:00 cybai joined
19:03 <zfnmxt> [exa]: My brain hurts. I tihnk I need to read more about MTL first :)
19:03 <zfnmxt> [exa]: Thanks a lot for all your help, at any rate
19:03 quobo joined
19:04 Deide joined
19:04 FreeBirdLjj joined
19:04 davr0s joined
19:05 nitrix joined
19:05 nitrix joined
19:05 mariatsji joined
19:06 sarna joined
19:06 path[l] joined
19:08 <[exa]> zfnmxt: the thing with the instance is basically telling the compiler that if it sees e.g. a monad 'Temp a' (which is in HasTemp) and it's wrapped in a transformer, the Transformer (Temp a) will also be in HasTemp (only with a slight lift)
19:09 <[exa]> which will eventually lift its way all the way down in your monad stack, collecting all the properties of the transformers you've used in a single place without any manual 'lift'
19:09 <infinisil> zfnmxt: Brains are 10% off at Walmart this week, if you want a new one, this is the time!
19:09 zakora joined
19:10 diwo joined
19:10 <zfnmxt> [exa]: It makes sense intuitively...but I think I need to do some more reading :)
19:12 connrs joined
19:12 acidjnk joined
19:13 <[exa]> zfnmxt: still I guess you've got better to implement it with a single State now. If you name your accessors reasonably, you'll be able to convert the code to transformers later without any serious rewriting
19:13 roconnor joined
19:14 spion joined
19:14 Kundry_Wag joined
19:14 <zfnmxt> [exa]: Can this be done just by using a basic transformer stack? I.e., how could I easily tack on the GenTemp to the stack without the (at the moment) more confusing MTL stuff?
19:15 ozzymcduff joined
19:15 beauby joined
19:15 <zfnmxt> Maybe once I understand that the MTL stuff will be easier
19:15 jbalint joined
19:15 jbalint joined
19:16 <[exa]> yeah, you'll only need to remember the correct amount of lifts you need to do for each transformer
19:16 <zfnmxt> I would have to change GenTemp from State to StateT, right?
19:16 <[exa]> yes
19:16 <zfnmxt> So change it to StateT, and put CheckerState inside of it, and viola
19:17 xkapastel joined
19:18 <[exa]> yes. I guess your GenTempT will even get the MonadTrans instance for free from StateT s, so you'll be able to use 'lift' right away
19:18 <dmwit> Put CheckerState inside of it, and BAM! Suddenly musical! 🎶
19:19 drets joined
19:19 <zfnmxt> Okay, cool. I'll do that as a stepping stone and then see if I can get the MTL approach down :)
19:19 <zfnmxt> Thanks a lot, [exa] !!
19:19 <[exa]> :]
19:19 <zfnmxt> dmwit: I hope so :)
19:20 ingenthr joined
19:23 knupfer joined
19:26 FreeBirdLjj joined
19:27 DSM joined
19:28 mariatsji joined
19:31 valentinbuza joined
19:34 <butterthebuddha> What's the best solution for maintaining (mutable) global state in a program?
19:35 UnChallengeD joined
19:36 <lyxia> pass around an IORef?
19:36 <monochrom> Most often you don't need it. In the minority of cases when you need it, "x = unsafePerformIO (newIORef blah)" with {-# NOINLINE x #-} is the standard solution.
19:37 <liste> or just making one in main and passing it around
19:37 <liste> ImplicitParams could be an option
19:38 <butterthebuddha> Is there any way to avoid having to pass around an extra parameter?
19:39 <liste> @define foo :: (?x :: Int) -> Int -> Int; foo y = ?x + y
19:39 <lambdabot> Parse failed: Parse error in type: ?x :: Int
19:39 roconnor joined
19:39 <philippD> When collecting constraints into a single type what are the benefits of creating a new class like `A` with a single `instance (constraints...) => A a` over using ConstraintKinds a defining a `type A a = (constraints...)` ?
19:39 <liste> > let { foo :: (?x :: Int) -> Int -> Int; foo y = ?x + y } in (let ?x = 5 in foo 10)
19:39 rcdilorenzo joined
19:39 <lambdabot> error:
19:39 <lambdabot> • Expected a type, but ‘?x::Int’ has kind ‘Constraint’
19:39 <lambdabot> • In the type signature: foo :: (?x :: Int) -> Int -> Int
19:39 canaria joined
19:40 <geekosaur> it's a constraint, not a type
19:40 <liste> > let { foo :: (?x :: Int) => Int -> Int; foo y = ?x + y } in (let ?x = 5 in foo 10)
19:40 <lambdabot> 15
19:40 <liste> look ma, no passing ?x to foo!
19:41 <monochrom> You can also let some library does it for you. global-config and global-variables do it.
19:41 dented42 joined
19:41 conn joined
19:41 rcdilorenzo joined
19:41 <lyxia> philippD: partial application, which is useful with higher-order constraint combinators.
19:41 <conn> how can the cartesian product of two monoids be a monoid ?
19:42 seangrove joined
19:42 <philippD> lyxia: Ahhh, that makes a lot of sense. Thanks.
19:43 <butterthebuddha> conn: apply the operation element-wise
19:43 <liste> mempty = (mempty, mempty); mappend (a, b) (a', b') = (mappend a a', mappend b b')
19:43 dan_f joined
19:43 <butterthebuddha> ^
19:44 phenoble joined
19:47 <conn> butterthebuddha can u give an example ? ;)
19:47 ZeuPiark joined
19:47 <ZeuPiark> hello
19:47 <butterthebuddha> conn: Let's think about the addition monoid over Integer
19:48 <butterthebuddha> I believe this is called "Sum" in Haskell
19:48 iAmerikan joined
19:48 <butterthebuddha> Let's try to define a monoid instance for Sum * Sum
19:48 <butterthebuddha> What does an element of Sum * Sum look like? It looks like (a, b) where both a and b are elements of this "Sum" type; i.e. they are Integers with addition defined on them
19:49 woodson joined
19:50 <butterthebuddha> If we have two elements of Sum * Sum, (a, b) and (a', b'), the most natural way of implementing (a, b) <> (a', b') is to simply do (a <> a', b <> b'). So for example, if the first element we pick from Sum * Sum is (1, 1) and the second element we pick is (2, 4), then (1, 1) <> (2, 4) would be (1 <> 2, 1 <> 4) = (3, 5)
19:50 <philippD> Hello ZeuPiark
19:50 <butterthebuddha> Does that make sense?
19:51 drets joined
19:51 <conn> <> equals mappend ?
19:51 <butterthebuddha> This is of course just one way to think about the product of two monoids as a monoid, but it's the most natural construction and satisfies the (category theoretic) universal property of Product
19:51 <butterthebuddha> conn: UYes
19:51 <butterthebuddha> Yes*
19:52 roconnor_ joined
19:52 <butterthebuddha> For a more complicated example, consider Sum * Product; (2, 4) <> (3, 1) = (2 <> 3, 4 <> 1) = (5, 4)
19:53 juliagoda joined
19:53 <butterthebuddha> (because (<>) = (+) in Sum and (*) in Product)
19:54 <conn> butterthebuddha i tried it like this: x = mappend [1,2] [] y = mappend [3,4] [] myMonoid a b = [ (m,n) | m <- a, n <- b] , which outputs: [(1,3),(1,4),(2,3),(2,4)]
19:55 <conn> where x and y should be monoids and myMonoid should be the new monoid made from x and y
19:55 <butterthebuddha> x and y are not monoids - they are elements of the List monoid
19:55 jbalint joined
19:55 jbalint joined
19:56 <butterthebuddha> In the code above, x = [1,2] and y = [3,4], so the corresponding element in the monoid that is the product of List with itself is ([1,2], [3,4])
19:56 <conn> how can i make x and y monoids ? from what i understood is that -- Identity laws x <> mempty = x
19:56 <butterthebuddha> x and y _cannot_ be monoids
19:56 <butterthebuddha> Only types of kind * -> * can be monoids
19:57 <glguy> *
19:57 <butterthebuddha> Whoops, kind *
19:57 <butterthebuddha> (Do you know what kinds are)
19:58 <philippD> x and y are values, not types and only types can be monoids
19:58 <butterthebuddha> It seems from our conversation that you are confused about what a Monoid is; I suggest you read the Typeclassopedia article here: https://wiki.haskell.org/Typeclassopedia#Monoid
19:58 <monochrom> > [1,2] <> mempty
19:58 <lambdabot> [1,2]
19:58 <monochrom> works
19:59 <butterthebuddha> (btw is there a list of lambdabot's abilities somewhere)
19:59 lambda-11235 joined
19:59 <monochrom> I have long lost that list.
19:59 <philippD> also your `myMonoid` has a signature that isn't compatible with mappend.
20:00 <Taneb> @djinn a -> (((a -> r) -> r) -> r) -> r
20:00 <lambdabot> f a b = b (\ c -> c a)
20:00 <Taneb> @@ pl djinn a -> (((a -> r) -> r) -> r) -> r
20:00 <lambdabot> pl djinn a -> (((a -> r) -> r) -> r) -> r
20:00 <Taneb> @@ @pl @djinn a -> (((a -> r) -> r) -> r) -> r
20:00 <lambdabot> f = flip id . flip id
20:01 <monochrom> You can also think of it as flip ($) . flip ($)
20:01 roconnor_ joined
20:01 <conn> butterthebuddha i read https://wiki.haskell.org/Monoid
20:01 fishythefish joined
20:02 <Taneb> monochrom: those are just two of my favourite things in lambdabot
20:02 <Taneb> (djinn and composition, I can take or leave pl)
20:02 dogweather joined
20:03 <butterthebuddha> conn: The first thing to understand is that in Haskell, Monoid is a _typeclass_. Thus, instances of Monoid must be types.
20:03 Raptor8m3 joined
20:03 <butterthebuddha> A good example of Monoid is the type [a]; another example is the type Maybe [a]
20:04 <butterthebuddha> (this can actually be generalized to Maybe a for any type a that implements Monoid)
20:04 <butterthebuddha> with me so far?
20:04 Deide joined
20:05 <conn> if [a] is my monoid can u give an example how to use it?
20:05 <zincy> Why can't * -> * be a monoid?
20:05 <monochrom> [1,2] <> mempty
20:06 <butterthebuddha> > [1,2] <> [3,4]
20:06 <lambdabot> [1,2,3,4]
20:06 <Taneb> zincy: that's a kind error. "Maybe -> Maybe -> Maybe" isn't a type that makes sense
20:06 <butterthebuddha> zincy: Types of kind * -> * are not "concrete"
20:06 <zincy> Think of <> as an operator that works on an type that has a monoid instance.
20:07 <zincy> This means that if we change our code to use different monoids we don't need to alter our operators
20:07 <butterthebuddha> To be able to define mappend and mempty, you need access to elements of a type
20:07 <butterthebuddha> Types of kind * -> * don't have any elements
20:07 <zincy> :k StateT
20:07 <lambdabot> * -> (* -> *) -> * -> *
20:07 <zincy> :k State
20:07 <lambdabot> * -> * -> *
20:07 <Taneb> (I think it's not quite right to even call things with kind * -> * "types")
20:08 <zincy> Ah
20:08 <butterthebuddha> Yeah I suppose they aren't types in the conventional sense
20:08 <conn> Of course, every Monoid instance should actually be a monoid in the mathematical sense, which implies these laws: mempty `mappend` x = x x `mappend` mempty = x (x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)
20:08 <zincy> So you cant combine sets of things that dont contain values
20:08 <zincy> :k State Int Int
20:08 <lambdabot> *
20:08 <butterthebuddha> zincy: Well
20:08 <dmwit> Different audiences/contexts will be more or less friendly to calling terms of kind * -> * "types".
20:09 <butterthebuddha> the way I would put it is that a type of kind * -> * is a "function"
20:09 <glguy> dmwit: Fortunately we're in #haskell
20:09 <zincy> So is it necessary but sufficient for monoid.. *
20:09 TCZ joined
20:09 <butterthebuddha> So it's not that it's an empty type
20:09 <butterthebuddha> but that it doesn't make sense for a type of kind * -> * to have elements
20:09 <dmwit> I think even different subsets of #haskell will have differing opinions on this. So best to establish your convention explicitly.
20:09 <zincy> How not?
20:09 <glguy> We can just stick with the Haskell Report's use for now
20:10 <dmwit> Then things of kind * -> * are perfectly good types.
20:10 <monochrom> In that case there is not even such as thing as "typeclass". It's "type class" in the Haskell Report. >:)
20:10 <plugin> So I have this 4gb csv I'm reading via Pipes.Parse and I don't know what encoding it uses. If I use the default utf-8, I end up processing about 1/10th the total rows. if I use latin, I process 99% of the rows, but values which are non-nullable are sometimes null and some columns have values they aren't allowed to.
20:10 danso joined
20:10 <butterthebuddha> zincy: Let's think about Maybe
20:10 <butterthebuddha> Does it make sense for "Maybe" to have elements?
20:10 <zincy> Maybe a surely has an infinite set of possible values
20:11 <butterthebuddha> Yes, but "Maybe a" for any type "a" has kind *
20:11 <zincy> No Maybe has no values
20:11 <monochrom> zincy, I want Text to be an instance of Monoid, and Text's kind is *
20:11 <zincy> Ok you win :)
20:11 <butterthebuddha> zincy: I don't really have a concrete answer for you, maybe someone else can provide a better argument than "it just doesn't make sense"
20:12 dogweath_ joined
20:12 <zincy> But I still feel slightly uncomfortable with whether Maybe has values. I am happy to say it doesnt have concrete values though
20:12 <dmwit> What is it that we're arguing?
20:12 <plugin> for kicks, I ran it through python's codec and rewrote it in utf-8. now I'm parsing more of the lines but it looks like I have exponential computational blowup as the parsing goes on. what gives?
20:12 <dmwit> zincy: There are no terms whose type is `Maybe`.
20:12 <zincy> Can Maybe be said in any sense to have values
20:12 <dmwit> zincy: (Not even `undefined`!)
20:12 <butterthebuddha> dmwit: I argue that it doesn't make sense for a type of kind "* -> *" to have values
20:13 <dmwit> Whether it makes sense is a completely different question.
20:13 <nitrix> zincy: You cannot have something of type `Maybe`, so there are no values (inhabitants).
20:13 <dmwit> But whether there are terms of such a type is an objective question, so I will focus on that one.
20:13 <nitrix> zincy: `Maybe` is a type constructor, it takes a type for argument.
20:13 <zincy> ok thanks
20:13 <butterthebuddha> I guess whether "it makes sense" comes down to your own personal beliefs
20:13 <glguy> Maybe is a type constructor , that tells us its capitalized
20:13 <glguy> its kind is * -> *, that tells us it takes an argument
20:13 <conn> butterthebuddha : if [a] type is a monoid then x = mappend [1,2] [] is a monoid ? since applying an empty list to a list does nothing
20:14 <dmwit> nitrix: (glguy's comments just there were aimed at you, I think. =)
20:14 <monochrom> conn, you are still conflating terms and types.
20:14 <butterthebuddha> conn: No, in that cacse x is _not_ a monoid; it's an element of the [a] Monoid
20:14 <butterthebuddha> Well, the [Integer] Monoid
20:14 <monochrom> Monoid is an adjective type types, not for terms.
20:15 <monochrom> It is as non-sensical as saying "15 is abelian".
20:15 tsaka__ joined
20:15 <butterthebuddha> conn: You are also not actually giving a definition for mappend or mempty
20:15 <glguy> nitrix: Don't forget that Int is a type constructor and (Either Int) is not. Int has kind *, so it takes no arguments and the type Either Int has kind * -> *, so we know it does
20:15 <conn> haskell wiki says: 1.2 Examples The prototypical and perhaps most important example is lists, which form a monoid under concatenation: instance Monoid [a] where mempty = [] mappend x y = x ++ y mconcat = concat
20:15 <butterthebuddha> conn: Maybe you need to read up some more/write some code that relates to typeclasses?
20:15 <zincy> :k Either Int
20:15 <lambdabot> * -> *
20:16 <zincy> How is that not a type constructor? :/
20:16 <butterthebuddha> zincy: it is
20:16 <glguy> because type constructor has nothing to do with kinds
20:16 <zincy> :o
20:16 <glguy> There are type constructors: Int Either Maybe, etc
20:16 <conn> butterthebuddha can you explain what haskell wiki menas by: lists which form a monoid under concatenation
20:16 <butterthebuddha> Well; I suppose
20:16 <glguy> and there are type variables: a b c proxy
20:16 <glguy> constructor vs variable is a lexical category
20:17 <dmwit> butterthebuddha: It isn't.
20:17 <butterthebuddha> conn: What that means is that the type [a] is Monoid, where "a" is a polymorphic type (i.e. it can be any type under the sun)
20:17 <glguy> where a is a type variable
20:17 <nitrix> Sarcasm doesn't play well when someone is actively asking for help. My coma should have been a period to not imply that one was related to the other, I'll accept my mistake there, but let's not confuse zincy.
20:17 <monochrom> conn: The sentence is referring to collection of all lists (not an individual list).
20:17 roconnor_ joined
20:18 <butterthebuddha> dmwit: glguy: I suppose I have always considered things that have a kind that's not * to be type constructors too, but that's technically wrong
20:18 <glguy> yeah, that's just wrong
20:18 language_agnosti joined
20:18 <monochrom> Just like the lone integer 15 is not abelian. It is the collection of all integers, under addition, that's abelian.
20:18 <zincy> Who is being sarcastic?
20:18 <dmwit> butterthebuddha: Yep, it's a very common error.
20:19 <butterthebuddha> conn: again I suspect that you are confused because you don't understand typeclasses and you should attempt to understand those before you tackle Monoids
20:19 jbalint joined
20:19 jbalint joined
20:19 <zincy> So how do we identify type constructors?
20:19 <zincy> Unapplied type functions?
20:19 <glguy> Type constructors are capitalized and exist in the type namespace
20:19 <zincy> Oh nice and simple
20:20 <glguy> Value constructors are capitalized and exist in the value namespace: True, Just, etc
20:20 <zincy> Thanks
20:20 <glguy> we have special case for operators to behave like that, we prefix those with :
20:20 <* hackage> typenums 0.1.1 - Type level numbers using existing Nat functionality http://hackage.haskell.org/package/typenums-0.1.1 (AdituV)
20:20 oisdk joined
20:21 <zincy> So why is (Either Int) not a type constructor?
20:21 <butterthebuddha> So is using the State monad a good way to introduce global state to a program? I've never used it before
20:21 <glguy> it's a type expression formed from the application of one type identified by its type constructor to another
20:21 <butterthebuddha> zincy: "Either" is a type constructor
20:21 <butterthebuddha> ("Either" int) is a type constructor that takes two type arguments and has one of them applied
20:22 <monochrom> "type constructor" is a very syntactic notion, not a semantic notion.
20:22 Luke joined
20:22 <glguy> Either and Int are type constructors, (Either Int) is the application of Either to Int, it's a whole expression, not a name
20:22 <zincy> State monad doesn't give you global state does it?
20:22 <butterthebuddha> *not a type constructor
20:22 <monochrom> In other words only a parser would care.
20:22 <zincy> hahaha
20:22 <conn> butterthebuddha : typeclasses If a type is a part of a typeclass, that means that it supports and implements the behavior the typeclass describes.
20:22 XorSwap joined
20:23 <butterthebuddha> conn: Now, a Monoid is a *typeclass*; what this means is that if a thing X is a Monoid, then that thing X has to be a *type* and *cannot be a value*
20:24 <conn> you mean like 3 is and Integer type, X is an Monoid type ?
20:24 <nitrix> glguy: Curiously, if Either is a type constructor, accepting two concrete types, could (Either Bool) been seen as partial application of the constructor, giving us yet another type constructor, accepting only one concrete type this time?
20:24 <butterthebuddha> conn: 3 is an element of the Integer type, and the Integer type is a Monoid, yes
20:24 <nitrix> glguy: There should be a close relation to how Big Lambda works there.
20:25 <butterthebuddha> nitrix: I think it's like a matter of terminology?
20:25 <conn> so how can i make use of the Monoid type ?
20:25 <zincy> conn: Types can have instances of typeclasses
20:25 <zincy> conn: you define an instance of monoid for your type
20:26 canaria joined
20:26 <zincy> Look at the monoid instance for lists to get started
20:26 <butterthebuddha> conn: Monoid is one of the more abstract typeclasses; I don't know of any easy use cases that aren't stupid and forced for the sake of examples
20:26 <butterthebuddha> conn: But essentially, if a type implements a Monoid
20:26 <butterthebuddha> then you can "combine" elements of that type
20:27 <butterthebuddha> This gives you certain guarantees when working with types
20:27 <butterthebuddha> Typeclasses in general are all about "providing guarantees" about what you can do with a type
20:28 <jle`> wait what, easy monoid use cases come up all the time
20:28 <jle`> > mconcat ["hello", "world"]
20:28 <lambdabot> "helloworld"
20:28 parenthetical joined
20:29 <monochrom> All type classes are abstract.
20:29 <zincy> <> is supposed to be associative but ...
20:29 <glguy> nitrix: No, it wouldn't make sense to think of Either Int being a new type constructor any more than map succ is a new variable
20:29 rzp joined
20:29 <butterthebuddha> Yes, but what I meant was to illustrate the true power of Monoids
20:29 <zincy> [1] <> [2] == [2] <> [1]
20:29 <jle`> zincy: you might be thinking of commutativity
20:29 <butterthebuddha> zincy: that's commutativty and monoids don't satisfy that in general
20:29 <jle`> > ("hello" ++ "world") ++ "goodbye"
20:29 <lambdabot> "helloworldgoodbye"
20:29 <butterthebuddha> I mean [1] <> [2] is kind of a stupid example
20:29 <butterthebuddha> When talking about Monoids
20:30 emilypi joined
20:30 <nitrix> glguy: Not quite. map is a function, you partially apply an argument, you still obtain a function. Either a type constructor, you partially apply it, you should still obtain a type constructor. I mean, its kind allows currying, doesn't it?
20:30 <jle`> mconcat shows the power of monoids in a great way, i think
20:30 <monochrom> In that case I like to keep it stupid and simple so yeah it's stupid which is a good thing. :)
20:30 <butterthebuddha> A better use case would be a polymorphic function that needs to be able combine elements of a type
20:30 <jle`> yeah, like mconcat :)
20:30 <zincy> Why is it a stupid example?
20:30 <butterthebuddha> but doesn't care how the actual combining is done
20:31 <monochrom> In that case Monoid is a fairly simplistic class in the first place because <> is rather bland.
20:31 <jle`> i don't think it's a particularly stupid example
20:31 <monochrom> I mean, it is not even gropu theory.
20:31 <butterthebuddha> monochrom: What I meant was that Monoid is more abstract than Num and Ord which are inspired by everyday and elementary mathematical considerations
20:32 <conn> like this : data Mytype = Custom Int then i make an instance for Mytype in Monoid class like : instance Monoid Mytype where mempty = 0 mappend (Custom x) (Custom y) = x + y.
20:32 <butterthebuddha> Regardless, the concept of a monoid is difficult for someone to grasp if one hasn't seen any rigorous math
20:32 <nitrix> glguy: Where is my understanding failing? What makes it not be a type constructor? Other than "no", what's the reason?
20:32 <jle`> is monoid really that difficult for people to grasp?
20:32 <zincy> butterthebuddha: I can understand monoids easily and I have never seen rigorous math
20:32 <jle`> conn: try (Custom 0) instead of 0
20:32 <electrocat> conn: no, the result should be of Mytype
20:32 <zincy> Its like the simplest typeclass out there
20:33 reactormonk joined
20:33 <monochrom> Monoid is inspired by strings and sequences which are everyday elementary programming considerations. Hell did you know that Tcl is based on only one monoid --- strings?
20:33 raoult joined
20:33 <butterthebuddha> Well monoids and groups were certainly very unfamiliar for me
20:33 <butterthebuddha> and I had trouble seeing motivation
20:33 <jle`> i feel like most programmers especially have several examples of monoids that they run into every day
20:33 <butterthebuddha> until much later
20:33 <butterthebuddha> I suppose that's not the case for everybody
20:33 <jle`> mconcat is a good example, i think
20:34 <monochrom> Err I guess s/Tcl/shell scripts/ . Tcl is based on lists in general.
20:34 <jle`> mconcat [] = mempty
20:34 replay joined
20:34 <jle`> mconcat (x:xs) = x <> mconcat xs
20:34 path[l] joined
20:34 dogweather joined
20:34 <jle`> now any type that implements mempty and <> can use mconcat
20:34 <jle`> > mconcat ["hello","world","bye"]
20:34 <lambdabot> "helloworldbye"
20:35 <jle`> > mconcat [Sum 3, Sum 10, Sum (-6)]
20:35 <lambdabot> Sum {getSum = 7}
20:35 <jle`> > mconcat [Any True, Any False, Any False]
20:35 <lambdabot> Any {getAny = True}
20:35 <monochrom> unfamiliar ≠ abstract
20:35 jbalint joined
20:35 jbalint joined
20:35 <monochrom> unfamilar = you didn't know someone gave it a name
20:36 <glguy> nitrix: instead of trying to redefine type constructor to match what you thought it will be better just to learn about what it is
20:36 <jle`> mconcat is an extremely powerful operation that can basically be used to unite many different things that we originalyl thought wer eall separate.
20:36 <jle`> nitrix: type constructors exist at the token level, not at the level of any actual semantic concepts
20:36 <zincy> glguy: So Type Constructor is just a semantic name for capitalised words in the type namespace?
20:37 <monochrom> "type constructor" is analogous to "data constructor" they are just for syntactic sake you don't go around saying "(:) True is a data constructor"
20:37 <zincy> So it only comprises one token
20:37 <zincy> monochrom: I do :)
20:37 <nitrix> Even at the token level, it's still valid for the instance declaration form, instance (a1, ..., an) => class t1 ... tm where ...
20:37 <jle`> yes, it's at the syntax level, not at the 'meaning' level
20:37 conn joined
20:37 <monochrom> Yeah sure hehe
20:37 <nitrix> Since those are types, not type constructors.
20:38 <nitrix> I don't know what glgul knows that I don't know about type constructors, but I'd really like him explaining instead of playing a cat-and-mouse game.
20:38 <monochrom> I go by the Haskell Report but I understand that postmodernism is the norm.
20:38 <jle`> you might be confusing 'Just', the data constructor, with 'Just', the function
20:38 fmixing joined
20:39 danthemyth joined
20:39 <zincy> nitrix: I think his explanation was sufficient for me
20:39 gehmehgeh joined
20:39 <jle`> Just is syntactically a data constructor, syntactically. like a literal, almost
20:39 <nitrix> zincy: Cool! Still, I have questions of my own :)
20:39 <jle`> and as a value, you can use it like a function
20:39 <monochrom> What cat-and-mouse game? I didn't see any.
20:39 <jle`> 'Either' is syntactically a type constructor, but you can use it as a * -> * -> * to get a * -> *
20:39 <zincy> nitrix: Perhaps I dont understand it though hehe
20:39 <conn> jle`: i tried this: data Mytype = Custom Int deriving Show instance Monoid Mytype where mempty = (Custom 0) mappend (Custom x) (Custom y) = Custom x myMonoid = mappend (Custom 5) (Custom 6) main = do print $ myMonoid
20:40 <jle`> the concept of a "type consturctor" and a "* -> * -> *" thing are separate, we just use the letters E-i-t-h-e-r to get a "literal" for a * -> * -> *
20:40 fmixing joined
20:40 <nitrix> I'm aware. Int is a valid type constructor.
20:40 <nitrix> Despite the `*` kind.
20:40 <zincy> conn: Have a look at http://lpaste.net/
20:40 <jle`> conn: nice :)
20:41 <jle`> that should work syntactically
20:41 <jle`> unfortunately the operation you defined is not monoidal/doesn't satisfy the laws
20:41 <electrocat> conn: not 'mappend (Custom x) (Custom y) = Custom (x + y)' ?
20:41 <nitrix> jle`: I'm aware. See above. But claiming (Either Bool) is not a type constructor is something else. Why would it not be? Exemples? Proofs? Anything substential?
20:42 <zincy> This is more of a general programming question but here goes the project is Haskell I promise
20:42 machined1od joined
20:42 <zincy> How do you structure your messaging around game updates for a game server to its clients. Would you always send the entire game state to clients or would you ever send additional messages of in game occurrences despite the fact they are derivable from the entire game state?
20:42 <monochrom> Definition of "type constructor" in the Haskell Report.
20:42 <nitrix> Other than "No", which I find almost insulting. It's a polite request, I don't know why I'm being nagged.
20:42 <electrocat> it's not a type constructor, technically it's a type application
20:42 <conn> electrocat: thanks thats what i was looking to do
20:43 <jle`> nitrix: yes, that syntactical structure is an application between two type constructors
20:43 <jle`> "type constructor" is the name of a type of leaf of the abstract syntax tree
20:43 <jle`> that's not a leaf, that's a node
20:44 <raoult> could anyone please help me with HIE in VS Code? my issue is that I need to pass -fobject-code (which I specified in the cabal file) but at some point this flag seems to get lost
20:44 <raoult> so I'm getting an error saying that I need to enable -fobject code
20:44 <jle`> data TypeExpression = TypeApplication TypeExpression TypeExpression | TypeConstructor String
20:45 <raoult> I don't know what I can do besides specifying this flag in the cabal file, is there any other location I should be adding this flag or something?
20:45 <electrocat> don't forget TypeVariable :)
20:46 <monochrom> It really annoys me, nitrix. glguy already typed in multiple sentences to explain why, long before you asked. But you ignore most of them and just pick out the "no" part and claim he's not explaining. You are the one insulting all his genuine effort.
20:46 <conn> jle` : electrocat: now the code looks like this https://pastebin.com/118fZuN6 , is myMonoid a monoid now ?
20:46 <nitrix> Is (Either Bool Int) a type constructor then?
20:46 <* hackage> yaml-pretty-extras - Extra functionality for pretty printing Yaml documents. http://hackage.haskell.org/package/yaml-pretty-extras- (locallycompact)
20:46 <nitrix> The report surely says it is, a nullary type constructor.
20:47 <electrocat> conn: yep :)
20:47 <jle`> nitrix: no, it is Appl (Appl (TyCon "Either") (TyCon "Bool")) (TyCon "Int")
20:47 <electrocat> Mytype you mean
20:47 <electrocat> ah
20:47 <electrocat> myMonoid as well
20:47 <jle`> the structure of a type expression is in 4.1.2 of the 2010 report
20:47 <nitrix> 4.1.1p1 `The symbol * represents the kind of all nullary type constructors.`
20:47 <jle`> nitrix: that is true, those two facts are not mutually exclusive
20:47 <conn> electrocat: ok since Mytype is a monoid now, how could i use 2 monoids and make a new one with using the cartesian product ?
20:48 <jle`> that's saying "All nullary type constructors have kind *"
20:48 <jle`> it's not saying "All kind-* things are nullary type consturctors"
20:48 <nitrix> What?!
20:49 <monochrom> Haha that's new to me, but I am OK with it. :)
20:49 <parenthetical> I want to compile AST-like like data to some kind of hidden implementation like so https://lpaste.net/5494303520037273600 -- is this possible?
20:49 <jle`> in the next section 4.1.2 it defines exactly what a type constructor is
20:49 <nitrix> Type expressions have different kinds, which take one of two possible form. The symbol * represents the kind of all nullary type constructors.
20:49 <nitrix> That's literally from the report.
20:49 fmixing joined
20:49 <nitrix> It's not the inverse... how that can be up for interpretation.
20:49 reygoch joined
20:51 <conn> jle` any idea on how to use the cartesian product on two monoids to make a new monoid ?
20:51 ixian joined
20:51 <jle`> nitrix: hm, okay, yeah, i think there might be a contradiction here then betweeen 4.1.1 and 4.1.2
20:52 <jle`> unless "nullary type constructor" includes things that aren't type constructors
20:52 <monochrom> To be fair, when I say "X is the set of all even integers" I don't mean "ah sometimes irrational numbers are also included".
20:53 wonko77 joined
20:53 <jle`> that's different than saying "X includes all even integers" though; that's more of a superclass kind of statement
20:53 <jle`> 4.1.2 clearly defines what the haskell report calls a type constructor, and i guess it does contradict that bullet point in 4.1.1
20:54 zero_byte joined
20:54 <nitrix> jle`: I'm looking at every paragraphs and none of them seems to hint that (Either Bool) wouldn't be a type constructor.
20:54 <jle`> it doesn't fall under the tycon category
20:54 <jle`> in the table at the start of 4.1.2
20:55 <nitrix> `gtycon` ?
20:55 <jle`> a type consturctor is one of five categories
20:55 <jle`> a string of letters and numbers and apostrophes with the first letter capitalized
20:55 <jle`> ()
20:55 <monochrom> Yeah, gtycon and qtycon are the type constructors in the grammar.
20:55 <fishythefish> I'm not seeing the contradiction between 4.1.1 and 4.1.2
20:55 <jle`> [], (->), and (,) (,,) (,,,) family
20:55 <electrocat> conn: cartesian product of what? two lists?
20:56 <jle`> conn: try writing it, data P a b = P a b
20:56 <jle`> conn: instance Monoid (P a b) where ....
20:56 seizo joined
20:56 <fishythefish> conn: didn't butterthebuddha explain that earlier? do all the monoid operations componentwise
20:56 <conn> electrocat: i should use the cartesian product on two monoids and it should give me a monoid
20:56 <nitrix> monochrom: Except that what you're describing are tokens that matches a gtycon rule. Where is the connection between that syntax and the semantic meaning of type constructor in that report?
20:56 language_agnosti joined
20:57 <nitrix> monochrom: Also, I'm trying to find `tycon` and I only find `gtycon`.
20:57 <jle`> nitrix: tycon is defined earlier
20:57 <jle`> nitrix: that's the point, though. that there is *no* semantic meaning of a type constructor
20:57 <jle`> it doesn't exist at the semantic level, only at the syntactic level
20:57 <jle`> it is purely a syntactic construct, nothing more
20:57 <monochrom> Yeah
20:57 <conn> electrocat: how could i do this with my actual code
20:58 <electrocat> conn: product on the type level? that would be a tuple?
20:58 oisdk joined
20:58 <jle`> nitrix: tycon is defined in 2.4, it has only one possible form/constructor
20:58 <jle`> "conid"
20:58 <jle`> tycon -> conid
20:59 <jle`> conid -> large {small|large|digit|'}
20:59 <conn> electrocat : make a tuple with list comprehension ? like [ (x,y) | x <- xs , y <- ys ]
20:59 <fishythefish> conn: you're working with Monoids, not lists
21:00 <jle`> the point that we're trying to make is that there is no such thing as a type constructor at the semantic level, it only exists at the syntactic/parsing/tokenization stage
21:00 language_agnosti joined
21:00 <electrocat> conn: i just don't know what kind of semantics you're looking for
21:00 <zincy> A type constructor is literally a name for a token to represent a type right?
21:00 <jle`> there is no connection between the syntactic type consturctor and the semantic type constructor because the semantic type constructor doesn't exist
21:00 crobbins joined
21:01 dogweather joined
21:01 marty_mc_fly[m] joined
21:01 <jle`> zincy: yes
21:01 <monochrom> Well, the other token is type variable
21:01 sheyll joined
21:02 <conn> electrocat: fishythefish: how could i apply the cartesian product on monoids in my actual code here, where Mytype is a monoid : https://pastebin.com/118fZuN6
21:02 <electrocat> conn: like [mappend x y | x <- xs, y <- ys] ?
21:03 <fishythefish> conn: none of what you have there is relevant; you need to write `instance (Monoid a, Monoid b) => Monoid (a, b) where ...`
21:04 <parenthetical> \
21:04 <jle`> conn: if X and Y are monoids, their cartesian product is (X,Y)
21:05 <nitrix> jle Except that 4.1.2p4 says "A parenthesized type, having form (t), is identical to the type t".
21:05 <jle`> conn: and (X,Y) also is a monoid
21:05 replay joined
21:05 <nitrix> jle` ^
21:05 <conn> fishythefish: explain further please, like this: instance (Monoid a, Monoid b) => Monoid (a, b) where mempty = (mempty, mempty) mappend (Monoid a, Monoid b) = ?
21:05 <jle`> conn: mappend (x,y) = ....
21:05 <fishythefish> conn: yes
21:05 <fishythefish> except you need to write mappend (x, y) =
21:05 <jle`> nitrix: what is that in response to?
21:06 <fishythefish> you don't pattern match on `(Monoid a, Monoid b)`
21:06 path[l] joined
21:06 <electrocat> not sure if he wants a product type of a value :p
21:06 <nitrix> jle` It appears (Either Bool) isn't a type constructor because it doesn't match the criteria that the syntax wants it to begin with an uppercase letter, but then there's this axiom that says `(t)` is the same as `t`.
21:07 <fishythefish> electrocat: his original question was how can the cartesian product of two monoids be a monoid
21:07 <monochrom> Yeah what is "cartesian product"?
21:07 <fishythefish> nitrix: yes, so (Either Bool) is the same as Either Bool as a type expression; that doesn't make it a type constructor
21:07 <jle`> yeah the full rules are:
21:07 <jle`> conid -> large {small|large|digit|'}
21:07 <jle`> so spaces are disallowed
21:08 <jle`> just 'small' letters, 'large' letters, digits, and '
21:08 Raptor8m3_ joined
21:08 <nitrix> I ran out of options to refute it.
21:08 ingenthr joined
21:08 <conn> fishythefish: now i get this error : Duplicate instance declarations: instance (Monoid a, Monoid b) => Monoid (a, b)
21:08 <fishythefish> trying to refute definitions tends to do that :P
21:08 <electrocat> conn: it's already defined
21:08 <fishythefish> conn: that's because it's already defined in the standard libas
21:08 <fishythefish> libs*
21:08 <jle`> conn: yeah, the instance already exists, so if you want to practice it, you'll have to define your own cartesiaon product type
21:09 <jle`> data (a :X b) = a :X b
21:09 <jle`> or just data CartProd a b = CP ab
21:09 <fishythefish> you can write `data Pair a b = Pair a b` and `instance (Monoid a, Monoid b) => Monoid (Pair a b) where ...`
21:10 <monochrom> Friday is bad for programming.
21:10 <nitrix> jle` monochrom Seems like the Haskell Report supports the claim, I can't find anything else that justify me hanging onto that old idea. I appreciate your time, both of you.
21:10 <monochrom> You're welcome.
21:10 <dysfun> days ending in a y are bad for programming
21:10 <jle`> no problem :)
21:11 seangrove joined
21:11 <fishythefish> jle`: btw, I don't think that bullet point in 4.1.1 leads to a contradiction
21:12 <fishythefish> * is the kind of all nullary type constructors, but not everything with kind * must be a nullary type constructor
21:12 <jle`> that's what i initially said
21:12 <monochrom> Yeah, but like I said, what do you make of "the set of all even integers"?
21:12 <jle`> but the paragraph above that says that there are only two categories of kinds
21:12 hpc joined
21:12 <jle`> so things that are kind * and not nullary type constructors...where are they covered?
21:13 <jle`> the paragraph above claims that the two bullet points are an exhaustive list
21:13 James joined
21:13 <fishythefish> ah, but the bullet points aren't classifying those things
21:13 <fishythefish> it's classifying the kinds they can have
21:13 <fishythefish> bullet point 1 is the base case, and bullet point 2 tells you how to apply an arrow kind
21:14 <jle`> hm, i see
21:14 <jle`> it might be more clearly written then
21:14 <Guest52948> I'm trying to get scotty to beam me up, but GHC seems to ignore the OverloadedStrings pragma...
21:14 <jle`> - The symbol *, which represents the kind of things including nullary type constructors
21:14 <electrocat> i'm not sure what this tycon disagreement is about :p
21:14 <jle`> - Their arrowing, * -> *, which represents the kinds of things...
21:14 conal_ joined
21:15 <jle`> electrocat: welcome to #haskell ;)
21:15 ggVGc joined
21:15 ggVGc joined
21:15 <jle`> it reminds me of traffic wave theory
21:15 <fishythefish> jle`: perhaps, but I'm reading it more as a set of axioms
21:15 <fishythefish> we can axiomatically take nullary type constructors to have kind *
21:15 <fishythefish> bullet point 2 says that we can get other things of kind * via type application
21:16 <jle`> ah i see
21:16 <jle`> that sounds like the right way to read that
21:16 <jle`> or at least, the reading that the authors had intended
21:16 <conn> fishythefish: something like this ? data Pair a b = Pair a b instance (Monoid a, Monoid b) => Monoid (Pair a b) where mempty = (Pair mempty, mempty) mappend (x, y) = (Pair x, y)
21:16 <jle`> conn: note that you aren't doing anything involving tuples anymore
21:16 <fishythefish> conn: almost, but you need `mappend (Pair x y)` since we're not matching tuples anymore
21:17 <Taneb> Guest52948: how are you passing the pragma?
21:17 <jle`> conn: are you familiar with ADT's ?
21:17 <fishythefish> similarly, mempty = Pair _ _, fill in the blanks
21:17 <jle`> @let data Pair a b = Pair a b deriving Show
21:17 <lambdabot> Defined.
21:17 <jle`> > Pair 3 '5'
21:17 <electrocat> jle`: is it purely about how the report should be interpeted? :p
21:17 <lambdabot> Pair 3 '5'
21:17 <Guest52948> Taneb: {-# LANGUAGE OverloadedStrings #-} at top of the file
21:17 <jle`> ^ that's how you make a Pair, not (Pair 3, '5')
21:17 dpyro joined
21:17 <Taneb> Guest52948: hmm, odd
21:17 <conn> jle` not familiar with ADT
21:18 <jle`> conn: do you know types like Maybe?
21:18 youtmon joined
21:18 <jle`> Either, lists?
21:18 <Taneb> Guest52948: what type are you expecting the overloaded strings to be?
21:18 <conn> fishythefish: got this error : Couldn't match expected type ‘Pair a b’ with actual type ‘(b0 -> Pair a0 b0, t0)’
21:18 <Guest52948> Taneb: The functions expect Text, but the actual types keep remaining String
21:18 <jle`> conn: do you know the 'Maybe' type, data Maybe a = Nothing | Just a
21:18 <fishythefish> conn: did you fix *all* the appearances of tuples?
21:19 <fr33domlover> data T a b = A a | B b is type application too though, right? "Type application" refers to the left side of the = not the right side
21:19 <Taneb> Guest52948: what happens if you also enable the NoMonomorphismRestriction extension?
21:19 <jle`> Guest52948: OverloadedStrings doesn't implicitly convert all strings to Text
21:19 <fishythefish> conn: you should only have `Pair`s, no tuples anywhere
21:19 <Guest52948> Taneb: hmm let me try
21:19 <conn> fishythefish: thats the code now https://pastebin.com/tAkFE0JC
21:19 <jle`> Guest52948: so if you have a value that has type String, it won't be converted to Text automatically
21:20 <jle`> Guest52948: OverloadedStrings is actually really OverloadedStringLiterals
21:20 <fishythefish> conn: the problem is that the RHS of mappend and mempty is still written incorrectly
21:20 <Guest52948> Taneb: still the same
21:20 <jle`> Guest52948: it doesn't automatically convert any strings to texts, it just interprets the letters `"hello"` as a Text *literal*
21:20 <fishythefish> conn: mappend also needs to take 2 arguments, not 1
21:20 <jle`> Guest52948: it only applies to literals you type into your source code
21:21 <fr33domlover> :t pack
21:21 justSomeGuy_ joined
21:21 <lambdabot> error:
21:21 <lambdabot> • Variable not in scope: pack
21:21 <lambdabot> • Perhaps you meant one of these:
21:21 <Taneb> Guest52948: then remove the extension and listen to jle`
21:21 <jle`> Guest52948: can you paste your code maybe? it's hard to see exactly what's going on without seeing code :)
21:21 <Guest52948> :jle` I thought it'd "polymorphise" string literals...
21:21 <electrocat> Guest52948: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-string-literals
21:21 <Taneb> (I mean, remove NoMonomorphismRestriction)
21:21 <jle`> Guest52948: yes, that's what it does
21:21 <jle`> Guest52948: it polymorphises the literals
21:21 <jle`> Guest52948: it doesn't polymorphise String in general
21:22 <jle`> so if you have a value (x :: String), you can't pass x to a function expecting Text
21:22 <monochrom> It doesn't polymorphize variables or compound expressions.
21:22 <justSomeGuy_> Hey all, anybody willing to help out a new haskeller persistent and spock?
21:22 <jle`> Guest52948: it's hard to really see what's going on without seeing the code :)
21:22 <Guest52948> jle`: I'm simply passing a "..." literal to a function that expects Text
21:22 <jle`> justSomeGuy_: don't ask to ask, just ask :)
21:22 <monochrom> OK show code.
21:23 <jle`> Guest52948: ah, okay. then there's no other way we can help without seeing code
21:23 <Guest52948> it's the main example from scotty... hold on
21:23 <conn> mappend (Pair m n) (Pair x y) = ?
21:23 <Guest52948> http://hackage.haskell.org/package/scotty
21:23 <fishythefish> conn: good, now write the RHS
21:23 zar joined
21:23 <jle`> Guest52948: what's the error?
21:23 conal_ joined
21:23 <Guest52948> couldn't match expected type Text with actual type [Char]
21:24 <jle`> on what line?
21:24 <jle`> (what's the full error message?)
21:24 <jle`> @where lpaste
21:24 <lambdabot> http://lpaste.net/
21:25 <Guest52948> scotty.hs:13:7: error: • Couldn't match expected type ‘RoutePattern’ with actual type ‘[Char]’ • In the first argument of ‘get’, namely ‘"/:word"’ In the expression: get "/:word" In a stmt of a 'do' block: get "/:word" $ do beam <- param "word" lift (putStrLn "hello") html $ mconcat ["<h1>Scotty, ", beam, ....] | 13 | get
21:25 <Guest52948> oops
21:25 <Guest52948> it's complaining about all lines with a string literal in them...
21:25 <jle`> can you paste the file you are running too?
21:25 <jle`> it looks like it's different than the example code
21:26 <Guest52948> {-# LANGUGAGE OverloadedStrings #-} {-# LANGUAGE NoMonomorphismRestriction #-} module Scotty where import Web.Scotty import Data.Monoid (mconcat) import Data.Text.Internal.Lazy main = scotty 3000 $ do get "/:word" $ do beam <- param "word" lift (putStrLn "hello") html $ mconcat ["<h1>Scotty, ", beam, " me up!<h1>"]
21:26 <fishythefish> @where lpaste
21:26 <lambdabot> http://lpaste.net/
21:26 <jle`> LANGUGAGE
21:26 <Guest52948> oh my
21:26 <electrocat> LANGUGAGE :p
21:27 <Guest52948> no compile error in pragmas then...
21:27 <jle`> pragmas are just normal comments
21:27 <monochrom> See how much time could have been saved if you showed actual code
21:27 <jle`> {-# blah blah blah #-} is syntax for haskell comments :)
21:27 <Guest52948> monochrom: yeah...
21:27 <conn> fishythefish: not sure how could i make it ? mappend (Pair m n) (Pair x y) = Pair m n
21:27 <jle`> and yeah, that's why it's good practice to start the question with code and full error :)
21:27 <[exa]> I always thought that the # inside turns on somehow mandatory pragma parsing
21:27 <Guest52948> jle`: I didn't know that...
21:28 <jle`> [exa]: it's a warning i believe
21:28 <Guest52948> jle`: thanks
21:28 <monochrom> And yes unregconized pragmas are silently ignored.
21:28 <jle`> Guest52948: no problem :)
21:28 <fishythefish> conn: m and x are elements of the same monoid, n and y are elements of the same monoid
21:28 <[exa]> interesting
21:28 <fishythefish> conn: how would you interpret (1, 2) + (3, 4), for exampel?
21:28 <dukedave> What's a terse way to write a `chars` function which would turn `"foo"` in to `["f","o","o"]` ?
21:28 <fishythefish> example*
21:28 <jle`> > map (:[]) "foo"
21:28 <lambdabot> ["f","o","o"]
21:28 <jle`> the trusty ol' robot monkey operator
21:28 <dukedave> Arg, I was so close, thanks @jle` !
21:29 <jle`> np :)
21:29 <electrocat> monkey operator :p
21:29 <dukedave> Ha, I see it now :)
21:30 reygoch joined
21:30 <conn> fishythefish: interpret ? (1,2,3,4) ?
21:30 <fishythefish> conn: well, for it to be a monoid, the output type must be the same as the input type
21:31 plugin_ joined
21:31 <jle`> conn: what do you think the mappending operation for (Sum 3, "hello") <> (Sum 4, "world") should be?
21:31 <reygoch> Is it possible to print out full record type? I'd like to do something like :t undefined::MyRecord and get all fields form MyRecord with their types listed.
21:31 <fishythefish> (think of how you add vectors)
21:31 <jle`> what should the result be? it has to also be (Sum Int, String)
21:32 <conn> fishythefish: mappend (Pair m n) (Pair x y) = Pair m y
21:32 <jle`> reygoch: it is possible with GHC Generics, but it's not a function people have written i think
21:32 <jle`> there's no built-in that directly does that, even though it's possible to write it yourself
21:32 <jle`> (that works for all records)
21:32 <monochrom> Is "info MyRecord" enough?
21:32 <fishythefish> conn: that doesn't satisfy the monoid laws but does typecheck
21:32 <reygoch> yes, I assumed it is possible with generics, but I was hoping for a ready solution
21:32 <monochrom> err, ":info MyRecord"
21:32 <justSomeGuy_> I'm trying to setup a basic endpoint which takes an id and goes through a join table to return all joined records get ("songs" <//> var) $ \id -> do song <- getRecord404 $ SongKey id tags <- runSQL $ select $ from $ \(tag `InnerJoin` songTag) -> do on (songTag ^. SongTagTagId ==. tag ^. TagId) where_ (songTag ^. SongTagSongId ==. val (SongKey id)) return (tag) json $ object ["song" .= song, "tags"
21:32 <justSomeGuy_> oh god
21:33 <fishythefish> where @lpaste
21:33 <fishythefish> @where lpaste
21:33 <lambdabot> http://lpaste.net/
21:33 <jle`> ah yeah, i forgot ghci was magical :)
21:33 <reygoch> monochrom: no, I'm using type classes and type parameters so I want to see the resulting type
21:33 <justSomeGuy_> okay here's a writeup of my question: https://lpaste.net/9032809779654819840
21:34 <conn> jle`: [(Sum 3, Sum 4, "wold") , ("hello", Sum 4, "world") ]
21:34 <jle`> conn: remember the type has to also be (Sum Int, String)
21:34 <jle`> not [(...)]
21:34 <monochrom> I do think that [(Sum 3, Sum 4, "wold") , ("hello", Sum 4, "world") ] is a type error
21:34 <jle`> i think you might be misinterpreting 'cartesian product' in this context
21:35 <conn> fishythefish: how would i make it satisfy the monoid laws ?
21:35 <fishythefish> conn: you don't need to compute the cartesian product of the inputs - tuples/pairs are already cartesian products of their components
21:36 <fishythefish> you're trying to define a notion of combining them (componentwise)
21:36 <fishythefish> conn: for one thing, make sure that mempty acts as a left and right identity for mappend
21:37 <jle`> conn: try trying out things that typecheck, and try different things until they satisfy the laws
21:37 <monochrom> I did use "cartesian product" to refer to liftA2 f xs ys in my course. :)
21:37 <jle`> for examplke, here is one typechecking definition:
21:37 <jle`> mappend (Pair x1 y1) (Pair x2 y2) = Pair x1 y1
21:37 <jle`> do you see why that typechecks?
21:37 <jle`> s/why/that
21:37 <jle`> and then, can you check if it obeys the laws?
21:38 chaosmasttter joined
21:38 <conn> fishythefish : instance (Monoid a, Monoid b) => Monoid (Pair a b) where mempty = Pair mempty mempty mappend (Pair m n) (Pair x y) = Pair m y
21:38 <jle`> right, that typechecks :)
21:39 <jle`> now, can you check if it follows the laws?
21:39 <conn> this compiles but mappend still needs to be written correctly
21:39 <fishythefish> yes
21:39 <jle`> here's an example to try:
21:39 son0p joined
21:39 <jle`> (Pair (Sum 3) "hello") <> mempty
21:39 <jle`> the answer *should* be (Pair (Sum 3) "hello")
21:39 <jle`> since x <> mempty = x
21:39 <fishythefish> `Pair 1 2 <> Pair 0 0` yields `Pair 1 0`, so that violates the laws
21:39 <jle`> but, what does your instance give you?
21:40 codesoup joined
21:40 canaria joined
21:41 <jle`> (try it out on ghci :) )
21:41 ziyourenxiang_ joined
21:42 tokomak joined
21:42 amar joined
21:46 <conn> jle`: i tried this: let test = (Pair "hello" "abc") `mappend` mempty print $ test and output is: Pair "hello" ""
21:46 DSM joined
21:47 Tops21 joined
21:49 athan joined
21:49 <conn> fishythefish : now mappend works only if Pair contains strings but not with numbers like Pair 1 2
21:49 epsilonhalbe joined
21:49 <athan> Hey yall, how's everyone doing
21:50 <fishythefish> conn: are you talking about typechecking or correctness?
21:50 Luke joined
21:51 <conn> fishythefish: let test = (Pair "hello" "abc") `mappend` mempty print $ test let test2 = (Pair 1 2) `mappend` mempty print $ test2 , test works , test2 doesnt
21:51 epsilonhalbe left
21:52 <fishythefish> conn: and what do you mean by "works" and "doesn't"? what's the output?
21:52 <fishythefish> :t print
21:52 <lambdabot> Show a => a -> IO ()
21:52 athan joined
21:53 <athan> shoot, did I get kicked? Sorry for the spam
21:53 refold joined
21:53 <conn> fishythefish: output on test is: Pair "hello" "", test2 gives error: No instance for (Num a0) arising from the literal ‘1’ The type variable ‘a0’ is ambiguous
21:53 hiratara joined
21:53 <athan> if you were a one-stop-shop method to normalizing arbitrary images to a specific type (say, PNG), how would you do it? I was considering juicypixels or an imagemagick binding or something
21:54 <fishythefish> okay, so test typechecks but still has incorrect behavior, and test2 is failing to typecheck
21:54 ConTeXnician joined
21:54 <[exa]> athan: juicypixels is good if you want to run the image data through haskell's rts; I'd go with imagemagick if you don't need them
21:54 athan_ joined
21:54 iAmerikan joined
21:54 <athan> [exa]: Yeah I just want to turn `forall a. SomeKindaImageFormat a => a -> PNG` or something
21:55 <[exa]> athan: your connection seems to be dying a bit (reset by peer last tiem)
21:55 <athan> ahh, darn starbucks thwarting my efforts
21:55 athan_ left
21:55 urdh joined
21:55 <[exa]> why not hip?
21:55 <athan> hip? Hm
21:55 <conn> fishythefish: see the code now https://pastebin.com/AtPhe25n
21:56 <dukedave> @pl parseTile l = L.find ((==) l . show ) [Straight ..]
21:56 <lambdabot> parseTile = flip L.find [Straight..] . (. show) . (==)
21:56 <dukedave> ... is melting my brain :\
21:57 <[exa]> athan: it has many formats, doesn't unnecessarily unpack the data (iirc) and 'downsample' is here https://hackage.haskell.org/package/hip-
21:58 <athan> [exa]: hmm, I think I had better go with an imagemagick binding - this is for a production server
21:58 <athan> thank you for the suggestion though
21:58 <[exa]> dukedave: you can simplify that a bit by moving the show right to the list, like: ... = L.find ((==) l) (map show [Straight..])
21:58 <fishythefish> conn: right, so the type error is because literals like 1 and 2 are polymorphic and ghci doesn't know which instance of Num to use in order to show the result
21:59 <fishythefish> conn: try `Pair (1::Sum Int) (2 :: Sum Int) <> mempty`
21:59 <butterthebuddha> The process run by "createProcess" is printing after the haskell program has finished printing; is there a way to force the program to finish execution resuming with the haskell program?
22:00 <orion> https://gist.github.com/centromere/e229850efbbb276514a75c97cfe37691 <-- How do I specify that I want to use the default implementation for runFoo here?
22:00 <dukedave> [exa]: unfortunately that won't work because I want to find `Straight`, and not `show Straight`
22:00 <[exa]> athan: avoiding dependencies? if you're going for stability I'd generally avoid the glue layers to differently-managed packages
22:00 <fishythefish> butterthebuddha: waitForProcess?
22:01 <[exa]> dukedave: oh it returns the plain thing, yes. Sorry :]
22:02 <conn> fishythefish: output is: Pair (Sum {getSum = 1}) (Sum {getSum = 0})
22:02 <fishythefish> conn: yes, so it typechecks but gives you an incorrect answer
22:02 <[exa]> anyway that @pl is cool
22:02 <conn> fishythefish: incorrect answer is because my instance of mempty = Pair mempty mempty mappend (Pair m n) (Pair x y) = Pair m y ?
22:03 <fishythefish> conn: mappend is incorrect
22:03 canaria joined
22:03 <conn> fishythefish: how could i correct it?
22:04 <fishythefish> conn: imagine `Pair` represents a vector: e.g. Pair 1 2 represents going 1 unit in the x direction (right) and 2 units in the y direction (up). How would you add two vectors? Pair 1 2 + Pair 3 4
22:04 <geekosaur> butterthebuddha, without context… if you are feeding data to a process, you also want to close the Handle you're using before waiting for the process to exit, so it knows you've finished
22:05 <athan> [exa]: moreso memory overhead - I never know how haskell's stack could blow, unless I'm using something like conduit
22:05 <conn> Pair 1+3 2+4
22:05 emilypi joined
22:05 <athan> I also just feel like if the binding is somewhat sane, it shouldn't be too bad
22:05 <fishythefish> conn: exactly. Now do something similar with your implementation
22:05 <fishythefish> only instead of +, it's mappend
22:05 <athan> idk if I could store directly with imagemagick - we'll see
22:06 louispan joined
22:06 yeevy_ joined
22:06 <conn> fishythefish: mappend (Pair m n) (Pair x y) = Pair (mappend m x) (mappend n y)
22:07 <fishythefish> conn: excellent
22:07 <conn> fishythefish: it compiles and output is: Pair (Sum {getSum = 1}) (Sum {getSum = 2})
22:07 <fishythefish> conn: and does that make sense?
22:08 <conn> fishythefish: mathematically i think yes, because the identity memoty doesnt change the inout ?
22:08 <fishythefish> right
22:09 <conn> fishythefish: now this code impelemnts the behavior of the cartesian product on two monoids ?
22:09 <fishythefish> conn: this code says that the cartesian product of two monoids can itself be considered a monoid
22:09 <fishythefish> the `Pair a b` construction is the cartesian product itself
22:10 <fishythefish> and the `(Monoid a, Monoid b)` constraints tell us that the components of our product are themselves monoids
22:10 knupfer1 joined
22:12 <athan> shoot I'll just use `magick convert`
22:12 <conn> fishythefish: thats what i needed ! now the task says: Prove that the cartesian product of two monoids again is a monoid! So is the code i wrote the solution?
22:12 <fishythefish> conn: well, not really
22:12 <fishythefish> you've shown that you can write an instance that typechecks
22:13 <fishythefish> but verifying that the implementation satisfies the Monoid laws is something you have to do independently
22:13 <conn> fishythefish: i need to write a mathematical proof based on the code ?
22:13 <fishythefish> that's more a mathematical exercise than a programmatic one
22:13 <fishythefish> conn: no, you can write a mathematical proof without any code at all
22:14 <fishythefish> really, the code should be based on the math
22:14 lortabac_ joined
22:14 <conn> fishythefish: so i need to write a proof without any haskell code? or extend my code so it satisfies the monoid laws ?
22:15 <fishythefish> conn: your code already satisfies the monoid laws, but the typechecker does not verify that proof for you
22:15 <fishythefish> you need to argue separately that it satisfies the monoid laws, because we've already seen you can write an implementation which violates them but still typechecks
22:16 <conn> fishythefish: how would i argue any example ?
22:16 <fishythefish> conn: you need to show that mempty is a left identity, that mempty is a right identity, and that mappend is associative
22:17 elfets joined
22:18 pavonia joined
22:19 <fishythefish> conn: i.e. show that `Pair a b <> mempty == Pair a b`, `mempty <> Pair a b == Pair a b`, and `Pair a b <> (Pair c d <> Pair e f) == (Pair a b <> Pair c d) <> Pair e f`
22:19 <fishythefish> you just need to perform simplification and apply the underlying Monoid instances you already have
22:20 codesoup joined
22:20 Tops2 joined
22:20 Linter joined
22:21 <conn> fishythefish: this is like the mathematical laws of monoids : -- Identity laws x <> mempty = x mempty <> x = x -- Associativity (x <> y) <> z = x <> (y <> z)
22:21 <fishythefish> conn: precisely
22:23 pounce joined
22:23 <conn> fishythefish: now i so ehow write a proof by induction for this laws applied on my code ?
22:23 Welkin joined
22:23 <fishythefish> conn: you shouldn't need induction
22:24 Welkin left
22:24 kefin_ joined
22:24 kefin joined
22:25 enzo-hauss joined
22:26 iAmerikan joined
22:26 <maerwald> any good unicode plugin for vim haskell
22:27 emilypi joined
22:28 <conn> fishythefish: could i do it like this for every law write: Pair x y and the output of it ?
22:28 LiaoTao joined
22:28 <fishythefish> conn: not sure what you mean. `Pair x y` doesn't really have output
22:29 <Tordek> conn: you prove it by manually applying your code and explaining how it behaves. e.g., id law 1 => x <> mempty = x => (Pair a b) <> (Pair 0 0) = Pair (a+0) (b+0) = Pair a b
22:29 <fishythefish> conn: in your mathematical formulation, you can replace `x` with `Pair a b`, `y` with `Pair c d`, and `z` with `Pair e f` and verify that you do get equalities
22:31 hiratara joined
22:31 <Tordek> (Or, more genereally, ... <> (Pair mempty mempty) => Pair (x <> mempty) (y <> mempty), and by id property that's Pair x y
22:32 <Tordek> repeat (applying relevant rules in each step) for all properties
22:33 canaria joined
22:35 _bo joined
22:35 woodson joined
22:35 errst joined
22:37 <conn> fishythefish: you mean like this ? https://pastebin.com/fCXE5bSd
22:39 bo joined
22:40 <Tordek> conn: that's not proving anything, you're just stating the laws
22:41 __bo joined
22:41 <conn> Tordek: how would i prove the first law ? add an example ?
22:41 <Tordek> read what I said above
22:42 m0rphism joined
22:43 <conn> Tordek: ok thanks for the hint, ill try to rewrite it now
22:47 johnw joined
22:47 lambdamu joined
22:47 vukasink joined
22:47 parsnip joined
22:47 plugin joined
22:49 lambdamu joined
22:50 codyw joined
22:53 youtmon joined
22:56 ingenthr joined
22:56 progfun joined
22:58 MP2E joined
22:59 conn joined
22:59 amar joined
23:01 nitrix joined
23:01 conal joined
23:04 RTZ0x859 joined
23:05 mountaingoat joined
23:06 mizu_no_oto_work joined
23:08 crobbins joined
23:09 conn joined
23:09 fmixing joined
23:10 element_ joined
23:10 <conn> Tordek: how about this ? https://pastebin.com/khmz4GVj
23:11 <* hackage> forkable-monad - An implementation of forkIO for monad stacks. http://hackage.haskell.org/package/forkable-monad- (mpahrens)
23:12 <* hackage> forkable-monad - An implementation of forkIO for monad stacks. http://hackage.haskell.org/package/forkable-monad- (mpahrens)
23:13 <Tordek> conn: I made an amendmwnt after my first example: you shouldn't use 0/+ but mempty/<> since your type is meant to work on monoids, not just numbers
23:14 <* hackage> forkable-monad - An implementation of forkIO for monad stacks. http://hackage.haskell.org/package/forkable-monad- (mpahrens)
23:14 ericsagn1 joined
23:15 <Tordek> in the case of proof of assoc, the best way is to evaluate each side separately and prove the result is the same
23:16 <conn> Tordek: niw change the 0 to mempty and =
23:16 <conn> and + to <>
23:17 tjbp joined
23:18 pounce joined
23:18 theDon joined
23:18 <Tordek> conn: the point is that you're starting from your own definitions: mempty = Pair mempty mempty; mappend (Pair m n) (Pair x y) = Pair (mappend m x) (mappend n y)
23:18 <Tordek> and applying them:
23:19 <Tordek> x <> mempty => (Pair m n) <> (Pair mempty mempty) <- I've replaced x for an arbitrary instance of Pair, and just "evaluated" mempty; replaced it by its contents
23:19 ian_andrich joined
23:20 <Tordek> next step is to evaluate <>, just from your definitions, and you've defined it such that (Pair m n) <> (Pair mempty mempty) = Pair (mappend m mempty) (mappend n mempty)
23:21 emilypi joined
23:22 <Tordek> now you exploit the id property of whatever the inner monoid is (you know it's a monoid because you've declared your type to work on monoids), and since mappend m empty = m, those expressions evaluate as Pair m n
23:22 <Tordek> and since (Pair m n) <> mempty = [..steps..] = Pair m n, using only your definitions or the proofs of the other entities, you've proved it
23:23 <Tordek> be careful with your parentheses, however; Pair m n <> Pair x y is NOT the same as (Pair m n) <> (Pair x y)
23:24 brocoli joined
23:25 <Tordek> since you're proving properties, remember in each step to be clear and deliberate, not just to write everything in a single line: explain "this transformation is valid because of this definition"
23:27 ozataman joined
23:30 tzemanovic joined
23:33 danthemyth joined
23:33 patlv joined
23:36 louispan joined
23:36 t7 joined
23:36 <Tordek> https://lpaste.net/242062093354795008 conn here's a more complete example of the first proof
23:39 path[l] joined
23:46 ericsagn1 joined
23:46 athan joined
23:52 Linter joined
23:54 <conn> Tordek: for the first law like this ? https://pastebin.com/vY2MYYUr
23:58 <Tordek> conn: better; now do associativity :)
23:58 <Tuplanolla> I see a familiar name.
23:58 <Tordek> hey tup
23:59 <Tuplanolla> Good to see you join our cult.
23:59 <conn> Tordek: thanks! ok ill rewrite it now