<    April 2017    >
Su Mo Tu We Th Fr Sa  
 2  3  4  5  6  7  8  
 9 10 11 12 13 14 15  
16 17 18 19 20 21 22  
23 24 25 26 27 28 29  
00:00 cables- joined
00:00 <dzdcnfzd> Welkin: yes it does. Anyways, here's the paste of what I was trying to do, and failing: http://lpaste.net/7161564774432505856
00:00 fizbin joined
00:04 ChaiTRex joined
00:05 Shatnerz0 joined
00:05 nidzo_ joined
00:05 horatiohb joined
00:05 YongJoon joined
00:05 snowalpaca joined
00:06 <Cale> dzdcnfzd: Well, there are a lot of ways you could store the posts in memory
00:06 <dzdcnfzd> Cale: I'm wondering if it can be done in a pure value
00:06 <Cale> Yeah, probably
00:07 <Cale> I'm not sure about with servant though...
00:07 <Cale> hm
00:08 <Koterpillar> dzdcnfzd: maybe have a ServerT with a State [Post] in the monad chain?
00:08 <Cale> (I've never really used Servant)
00:09 <Cale> Or just StateT [Post] what you already have?
00:09 <Welkin> the only way to do it would be wrapping in StateT, yes
00:10 <Welkin> otherwise some kind of IORef/MVar/TVar whatever
00:10 binaryplease joined
00:10 <Welkin> it's much more of a pain in the ass than just using sqlite for your example
00:10 bhiliyam joined
00:10 snowalpaca joined
00:11 <Cale> That's kind of odd... I guess it comes out of the fact that Servant is doing a bunch of type-level magic, so you can't just arbitrarily change the type of the result of these actions.
00:16 <dzdcnfzd> Welkin: I understand this, but the issue is of sharing state between calls to the server
00:17 <dzdcnfzd> if the only way to do so is to use DBs, that has massive consequences for every part of the design
00:17 <dzdcnfzd> (or to use MVars, etc...)
00:17 nwf joined
00:17 acidjnk22 joined
00:18 <Eduard_Munteanu> There's acid-state if you don't mind keeping things in memory.
00:18 <dzdcnfzd> I'm just screwing around at this point, so it's no big deal to experiment
00:18 <Cale> Eduard_Munteanu: I think the problem dzdcnfzd is tackling is just how to carry anything along
00:18 <dzdcnfzd> Cale: exactly
00:19 <Eduard_Munteanu> Oh, you can definitely use MonadReader m => ServerT m ...
00:20 eschnett joined
00:20 Krymise joined
00:20 <Cale> Is it viable to attempt to define the server recursively?
00:20 <Cale> I've never really thought about that.
00:21 <dzdcnfzd> Cale: I don't think so, actually
00:21 steshaw joined
00:21 <dzdcnfzd> That's what I was trying to do
00:21 <dzdcnfzd> I couldn't
00:21 <dzdcnfzd> (I'm also very new to this library, so...)
00:22 benl23 joined
00:23 <Cale> I think if you get down to the level where you're writing the Handler actions
00:23 nighty-- joined
00:23 <Eduard_Munteanu> https://hackage.haskell.org/package/servant-server-0.10/docs/Servant-Server.html#g:5
00:23 <Eduard_Munteanu> See the enter example ^^
00:24 <Eduard_Munteanu> Although I remember I could do it without Nat stuff at all.
00:25 <Cale> Weird
00:26 darlan joined
00:27 alunduil joined
00:28 <Cale> Maybe tearing apart the implementation of serve somehow would also do it
00:28 jmcarthur joined
00:29 andyhuzhill joined
00:30 crobbins joined
00:34 johnw_ joined
00:35 fizbin joined
00:39 ChaiTRex joined
00:39 beerdrop joined
00:42 rcschm joined
00:42 <dzdcnfzd> Eduard_munteanu: In that example, do you know what "C.." means?
00:43 <Eduard_Munteanu> dzdcnfzd, import qualified Control.Category as C
00:43 <glguy> C.. is a qualified operator symbol. C is a module name, . is the operator symbol and the middle . is like the one in Prelude.map
00:43 <Eduard_Munteanu> :t (C..)
00:43 <lambdabot> forall k (a :: k) (b :: k) (cat :: k -> k -> *) (c :: k). Category cat => cat b c -> cat a b -> cat a c
00:44 ick joined
00:44 <dzdcnfzd> Eduard_munteanu: Thanks :) Would not have caught that
00:44 flatmap13 joined
00:44 jgt4 joined
00:44 oisdk joined
00:45 biglambda joined
00:46 <Welkin> lol
00:46 <Welkin> that is too confusing
00:48 iCharlie joined
00:48 eacameron joined
00:49 fizbin joined
00:50 Goplat joined
00:52 <dzdcnfzd> http://lpaste.net/4447318255664627712
00:52 <dzdcnfzd> I think I would have been more weirded out if that HAD worked
00:52 <dzdcnfzd> but it doesn't
00:52 <dzdcnfzd> so no worry
00:53 <dzdcnfzd> It seems like you shouldn't be able to do this without relying on IO
00:53 <dzdcnfzd> otherwise you'd have pure functions spitting out different results
00:54 Krymise joined
00:54 electrostat joined
00:54 eacameron joined
00:56 jchia joined
00:57 carlosda1 joined
00:57 lavalike_ joined
00:58 coltfred joined
00:58 eacameron joined
00:59 codesoup joined
00:59 oisdk joined
00:59 fizbin joined
01:01 mavihs joined
01:02 lavalike joined
01:03 eacameron joined
01:04 fizbin joined
01:07 eacamero_ joined
01:09 nick123 joined
01:10 eacameron joined
01:11 Stanley00 joined
01:11 bhiliyam joined
01:11 <Eduard_Munteanu> The problem lies with getBlog and postBlog's types.
01:13 DrMentats left
01:14 JoshS joined
01:14 robertkennedy joined
01:14 Lord_of_Life joined
01:15 ddere joined
01:16 <ick> I've got a dumb question but I've just spent the last hour or so on it - How does one artificially limit the values a type can inhabit in Haskell? Specifically I'm looking to define a Sum Type that has the semantics of a type of command (e.g. readRegister | writeRegister) but carries with it a Word32 value. The Word32 value I'm hoping to limit to a small subset of actual Data.Word.Word32's. I guess on the
01:17 <ick> whole, the goal is to acheive something like a number of C #defines (ie. #define RReg 0x0000; #define WReg 0x0001;) and then tack on the extra constraint that only RReg and WReg are valid command types.
01:18 mkloczko joined
01:18 <ick> Best I've come up with is a CmdT type constructor that has 2 nullary(?) data constructors, and an auxillary function mapping those values to the Word32s
01:19 eacameron joined
01:21 takle joined
01:24 mulk joined
01:24 <ick> My other line of thinking, was to use the module system to somehow limit how one would construct a CmdT data value that ensures I can't construct a ( RReg 0x0001 ) value, or a ( RReg 0x0002 ) value.
01:25 eacameron joined
01:26 <ick> I guess I could rephrase the question as: How can I create a new type that inhabits a small subset of an already existing type? For example just the first 4 values of Int from 0-4
01:27 peterbec` joined
01:27 sword865 joined
01:28 myfreeweb joined
01:28 <Rembane> ick: That sounds an awful lot like dependent types and that's kinda hard in Haskell, even though there are some workarounds.
01:28 <monochrom> If there are only a few legal values, do not use Word32 directly in your sum type. Define "data R = RReg | WReg". Use R in your sum type. Have a separate interpreter or converter that maps RReg to 0, WReg to 1.
01:28 tgeeky joined
01:29 <monochrom> If there are too many legal values, then what you said about module system.
01:29 Geekingfrog joined
01:29 Arguggi joined
01:29 wroathe joined
01:29 acro joined
01:30 mdarse joined
01:30 YongJoon joined
01:30 eacameron joined
01:31 reynir joined
01:31 JDevlieghere joined
01:32 oleks joined
01:32 fizbin joined
01:32 gmhafiz_ joined
01:33 kriztw joined
01:33 recycletrash joined
01:34 <ick> monochrom: Thanks, I'll give it a go with what I have, the mapping between 0x0000-0x0004 and values of the Type, and see where I end up. Guess theres nothing better for learning it than to keep trying it.
01:34 liste joined
01:35 Krymise joined
01:35 Gurkenglas joined
01:36 eacameron joined
01:36 SimpleL joined
01:36 <ick> Rembane: I've heard of Dependent Types and.... my head exploded so I'm gonna try to avoid bringing those into my mental model for the moment :)
01:39 takle joined
01:40 eacamero_ joined
01:41 jsgrant_ joined
01:43 hc joined
01:43 edvorg joined
01:45 anuxivm left
01:46 solarus joined
01:46 Supersonic112_ joined
01:46 <joe9> any tasty users here. Do you know how to enable more verbose output? I am running it TMPDIR=/tmp/ghc stack test --file-watch --test-arguments --quickcheck-verbose
01:46 <joe9> . It does not show the input and the output. It just shows failed and is repeated that data.
01:47 Coldblackice joined
01:47 <joe9> I added trace to the test, but, the trace output is disappearing.
01:48 hc joined
01:48 eacameron joined
01:49 splanch_ joined
01:51 {emptyset} joined
01:52 <joe9> http://codepad.org/2cTa6JSY
01:52 eacamero_ joined
01:53 shayan_ joined
01:55 bertschneider joined
01:56 fizbin joined
01:56 dolio joined
01:58 carlosda1 joined
01:59 fizbin joined
01:59 takle joined
02:00 markasoftware joined
02:00 hucksy_ joined
02:01 acidjnk22 joined
02:01 halogenandtoast joined
02:03 fizbin joined
02:03 dolio joined
02:03 <rotaerk> hmm, I'm planning to use 0mq for inter-process communication, but it only solves the problem of how they communicate, and not what's actually sent
02:03 flump joined
02:04 eacameron joined
02:04 <monochrom> Send Morse code. :)
02:04 <rotaerk> any recommendations for an approach to actually encode messages to be sent?
02:04 <rotaerk> lol
02:05 tathougies joined
02:05 <rotaerk> just wondering if there's something that's particularly nice in haskell
02:05 indi_ joined
02:05 exferenceBot joined
02:05 <pacak> https://flagexpressions.files.wordpress.com/2010/03/semaphore-flag-codes3.jpg
02:05 <monochrom> I think some people use the binary package, some others use cereal.
02:05 <peddie> rotaerk: would the `binary` or `binary-serialise-cbor` packages work for you?
02:06 <rotaerk> hmm thanks; lemme check
02:06 <rotaerk> I see two 'binary's; looking at that first :P
02:06 reiddraper left
02:08 <pacak> rotaerk: I'm using beamable (current version on hackage is outdated). It derives stuff with generics, works with arbitrary data, contains checks to ensure that data representation is the same on both sides, kind of fast and generates compact representation.
02:09 <rotaerk> okay, yea any of these will likely do nicely; thanks for the suggestions
02:09 ericmathison joined
02:10 wroathe joined
02:11 nick123 joined
02:11 dan_f joined
02:11 hexagoxel joined
02:12 noan joined
02:12 liste joined
02:12 bhiliyam joined
02:13 keep_learning joined
02:14 ichor joined
02:14 Arguggi joined
02:14 JeanCarloMachado joined
02:15 eacameron joined
02:16 darjeeling_ joined
02:16 mdarse joined
02:16 chenshen joined
02:19 fermi_ joined
02:19 eacameron joined
02:19 acro joined
02:20 takle joined
02:23 infinity0_ joined
02:23 infinity0_ joined
02:23 Krymise joined
02:24 fizbin joined
02:25 eacameron joined
02:26 infinity0 joined
02:27 vektorweg1 joined
02:28 pavonia joined
02:29 infinity0 joined
02:30 wroathe joined
02:31 cic joined
02:31 infinity0 joined
02:32 takle joined
02:32 sdothum joined
02:33 eacameron joined
02:33 dktn joined
02:34 infinity0 joined
02:35 johnw_ joined
02:35 Argue joined
02:36 eacamero_ joined
02:36 hexfive joined
02:37 infinity0 joined
02:37 Destol joined
02:40 robkennedy joined
02:40 skeuomorf joined
02:41 wroathe joined
02:44 Rodya_ joined
02:46 tctara_ joined
02:47 eacameron joined
02:47 nomicflux joined
02:48 takle joined
02:49 sellout- joined
02:50 rcschm joined
02:50 ericmathison joined
02:50 eacameron joined
02:51 MP2E joined
02:51 Argue_ joined
02:52 geekosaur joined
02:52 dan_f joined
02:54 xtreak joined
02:55 eacamero_ joined
02:56 meandi_2 joined
02:57 indi_ joined
02:58 flatmap13 joined
02:58 cpup joined
02:58 carlosda1 joined
03:00 teggi joined
03:01 sleffy joined
03:01 wroathe joined
03:01 eacameron joined
03:03 exferenceBot joined
03:04 xtreak joined
03:04 thunderrd_ joined
03:06 Argue_ joined
03:06 harfangk joined
03:06 ebzzry joined
03:08 DataComputist joined
03:08 Lu joined
03:10 hexagoxel joined
03:11 sanitypassing joined
03:12 wroathe joined
03:12 eacameron joined
03:12 dfeuer joined
03:13 bhiliyam joined
03:13 robertkennedy joined
03:13 ogre joined
03:15 recycletrash joined
03:18 felixsch__ joined
03:18 j2j joined
03:19 systemfault joined
03:21 systemfault joined
03:21 wroathe joined
03:22 xtreak joined
03:23 emmanuel_erc joined
03:24 ForgedPancake joined
03:24 markasoftware joined
03:24 eacameron joined
03:26 <iqubic> I'm back.
03:26 rcschm joined
03:27 <benzrf> me too thanks
03:32 sleffy joined
03:32 eacameron joined
03:32 wroathe joined
03:35 raycoll joined
03:36 takle joined
03:39 eacameron joined
03:40 safe joined
03:42 wroathe joined
03:42 hybrid joined
03:42 skeuomorf joined
03:43 dfeuer joined
03:43 iqubic joined
03:43 <iqubic> Hello All.
03:44 <iqubic> Who's ready for me to design a game in Haskell. Or is Haskell not the right language for that?
03:45 brynedwardz joined
03:45 jmcarthur joined
03:45 {emptyset} joined
03:45 takle joined
03:46 <peddie> iqubic: I'm ready for you to do it
03:47 <iqubic> Is Haskell the right langage for game development?
03:47 <Sornaensis> depends on what your goals are and how familiar you are with haskell/fp
03:47 <peddie> iqubic: what kind of game are you writing? for the most part I don't see why not
03:48 <Sornaensis> many people have made games in haskell, including live coding VR games
03:48 <jle`> iqubic: the infrastructure/ecosystem won't be as established as other language ecosystems, but haskell the language itself has a lot of advantages going for it
03:48 eklavya joined
03:52 wroathe joined
03:53 MP2E joined
03:53 chenshen joined
03:54 des_ joined
03:54 <iqubic> What advantages does Haskell have for developing games?
03:55 <peddie> iqubic: same advantages it has for developing other kinds of programs I imagine
03:56 <iqubic> Which are...?
03:56 <jle`> refactorability, type-safety
03:57 <jle`> equational reasoning, composability
03:57 <jle`> maintainbility
03:57 <jle`> verifiability
03:57 Xanather joined
03:57 <jle`> scalability, etc.
03:58 Xanather joined
03:58 takle_ joined
03:58 <jle`> so if you like building games that are maintainable on the long run, then haskell is probably a good choice. if you want to hack something together really quickly with well-established libraries then it might not be the best choice for a game
03:58 <jle`> not saying that type safety doesn't help you develop programs quickly, though :)
03:59 Koterpillar joined
04:03 djapo joined
04:06 takle joined
04:07 <Cale> Yeah, the biggest problem writing games in Haskell is that you'll often be treading new ground, rather than anything intrinsic to the language.
04:09 linelevel joined
04:11 <Cale> At some point, it'll be fun to push Reflex into game engine territory. A lot of its design points came out of a lot of ideas that Ryan Trinkle and Stephen Blackheath and I developed working on an FRP system for an ARPG we were working on back in 2011 or so. (Sadly didn't get released, but we sort of proved to ourselves that it could work.)
04:11 <Cale> Ryan's made Reflex a way better FRP system than we had back then even
04:12 nick123 joined
04:12 <joe9> check out ekmett's quine . there are some cool GL stuff there.
04:12 splanch joined
04:13 <benzrf> Cale: arpg?
04:13 <benzrf> joe9: thats all shader stuff, not ordinary 3d - im not sure whether its appropriate for agms
04:13 <benzrf> *games
04:13 BartAdv joined
04:13 bhiliyam joined
04:13 <orion> Hi. I have functions like, "x :: Foo -> Bar -> (Info -> Info)" and "y :: Baz -> (Info -> Info)", etc. The common thread between them is that they all return (Info -> Info). What is the proper way to create a list of all these functions, given that common property?
04:14 mizu_no_oto joined
04:14 <Koterpillar> orion: partially apply them
04:14 nullcone joined
04:14 chenshen joined
04:14 mazeinmaze_ joined
04:15 <iqubic> Koterpillar: How would that work??
04:16 <Koterpillar> :t [x somefoo somebar, y somebaz] -- [Info -> Info]
04:16 <lambdabot> error:
04:16 <lambdabot> • Couldn't match expected type ‘t1 -> t0 -> t’
04:16 <lambdabot> with actual type ‘Expr’
04:16 <iqubic> Also, orion, the parentheses are not needed.
04:18 <Cale> benzrf: It was called Bloodknight. You ran around with a giant hammer and smashed monsters and the plan was to have a magic system that interacted with the blood on the ground. We had some melee and ranged AIs, an open world with dynamically loaded tiles. Combat was reasonably fun, but the world was still pretty empty and we still needed to build quite a lot of content, and the FRP system was still not *quite* where we wanted it at the
04:18 <Cale> end of the project.
04:19 <Cale> benzrf: Still, the research project half of it was good, and it's easier to make money building web applications, it turns out.
04:19 freeside joined
04:21 fermi_ joined
04:25 darjeeling_ joined
04:26 <iqubic> What's an ARPG?
04:26 <iqubic> And don't most games require a mutable state?
04:27 <MarcelineVQ> usually action rpg which is an action game where you can improve stats or skills by defeating enemies
04:28 <iqubic> Ah.
04:28 <Cale> Also, Haskell has plenty of ways to deal with mutable state
04:28 <iqubic> Is there a guide to the reflex library anywhere. I want to learn about FRP.
04:28 <iqubic> Cale: Like what?
04:29 <jle`> haskell is pretty good at dealginw ith mutable state
04:29 <jle`> in fact i trust haskell to deal with mutable state more than i trust other languages
04:29 <iqubic> Cale, All I know about is IORef.
04:29 <jle`> haskell is where mutable state finally made sense to me
04:29 <iqubic> jle`: Why do you say that?
04:29 <MP2E> a thing that concerns me is the stop the world garbage collector, in the context of games.
04:29 <Cale> iqubic: IORef, MVar, boxed and unboxed mutable arrays of various kinds, STM for concurrent memory transactions...
04:30 <dfeuer> bitemyapp: ping
04:30 <MP2E> there are quite a few games where that doesn't matter but it'd be harder to make say, a AAA shooter or something similar
04:30 <Cale> There are weak references
04:30 <Cale> (Which is actually quite important)
04:30 <dfeuer> Weak references are a bit tricky to work with.
04:30 <iqubic> Cale: Haskell has Mutable arrays?
04:30 <dfeuer> iqubic: yes.
04:31 <iqubic> Can I get guides on how to use IORef, MVars, Mutable Arrays and STM?
04:31 <iqubic> Or should I looks those up myself
04:31 <Cale> iqubic: Sure, in the base package there's IOArray (mutable arrays with lazy elements) and IOUArray (unboxed mutable arrays)
04:31 <Cale> and then StorableArray for FFI
04:31 <iqubic> What's the difference between boxed and unboxed arrays?
04:32 <Cale> boxed arrays allow for polymorphism and lazy evaluation
04:32 <Cale> but they're effectively arrays of pointers to code
04:32 <iqubic> Cool.
04:32 <freeside> shouldn't we be talking about Data.Vector?
04:32 <Cale> and I was about to mention vector too
04:32 <dfeuer> Cale: that's not the base package; it's the array package. Unless you want to muck around with yucky things like GHC.Arr
04:33 <Cale> dfeuer: Oh, is it? Ah, right
04:33 <dfeuer> Does base even expose GHC.Arr? Looks internal.
04:34 <Cale> I figured it was base because the original Array was part of the Haskell spec, but I suppose not.
04:34 wroathe joined
04:35 <Cale> iqubic: Oh, and then there's analogously STArray and STUArray, which are basically the same thing, but for the ST monad.
04:35 nilg joined
04:35 <Cale> and then there's a library called Vector which redevelops all this stuff, and gives you operations with stream fusion for the immutable arrays
04:36 <Cale> (and iirc, there's some funky stuff it does for mutable ones, but I'm not sure stream fusion is all that meaningful for mutable arrays)
04:36 <freeside> first get it right, then make it fast
04:38 <dfeuer> For many purposes, I think the interface vector uses is better.
04:38 <Cale> I mostly agree
04:39 <Cale> With one caveat: it doesn't use Ix for some reason
04:39 <dfeuer> Another option is to build on the rather spare array API offered by the primitive package. It does everything absolutely necessary and not a shred more. There may be packages that build on it to give something better; dunno.
04:39 <dfeuer> Cale: because Ix is *weird*.
04:39 <Cale> It's not that weird...
04:39 <dfeuer> Pretty weird that you can go to and not fro.
04:40 <dfeuer> I remember it getting very badly in my way once.
04:40 <dfeuer> But I don't remember any details.
04:40 <dfeuer> Doesn't that let you convert an index to an Int, but not the other way 'round? SOmething like that?
04:41 <kadoban> I've really grown to like the 'array' package stuff, if that's what we're talking about. It's quite flexible
04:42 azahi joined
04:45 wroathe joined
04:46 Rodya_ joined
04:46 xtreak joined
04:47 <freeside> how do you folks keep up with the volume of CS research relevant to haskell programming?
04:48 <freeside> i find it a little overwhelming, all the functional pearls, and then inevitably the category theory
04:48 systemfault joined
04:48 <kadoban> CT and such don't seem to be that related to practical haskell programming. At least not much more than they're related to any language, IMO.
04:48 <dfeuer> CT seems to inspire some library authors.
04:49 <freeside> with other languages, to understand and use a language feature, you read a tutorial or a chapter of an o'reilly book. with haskell, you have to read somebody's PhD thesis and then reimplement it all from scratch because the code didn't survive the latex -> dvi -> ps -> pdf process.
04:49 <jle`> freeside: CS research relevant to haskell program is mostly just for fun
04:49 <jle`> most haskell is what you describe -- a tutuorial or a chapter of an o'reilly book
04:49 fakenerd joined
04:49 systemfault joined
04:49 <kadoban> freeside: I have absolutely never done anything approaching that for haskell and I get by fine
04:49 <MarcelineVQ> sometimes. allthough haskell phd thesis's for some reason tend to be extremely approachable
04:49 <jle`> i've never been required to read a phd thesis for anyhting in haskell..
04:50 <jle`> working with haskell practically is mostly reading blog posts and library tutorials
04:50 <iqubic> Anyone have a tutorial for mutable data in Haskell?
04:50 <freeside> maybe it's because i'm doing EDSL design and implementation in Haskell.
04:50 <jle`> i haven't really run into a situation where i needed to do anything remotely 'academic' to work practically in haskell
04:51 <jle`> and i've been using haskell for many years now, doing a lot of practical things with it
04:51 <jle`> as my main language for work and research
04:51 <jle`> disclaimer, it might be survivorship bias or something idk
04:51 <freeside> but don't you sometimes feel a bit anxious about the unknown unknowns?
04:51 justan0theruser joined
04:52 <MarcelineVQ> if programming was by the numbers you'd program a program to rogram
04:52 vlatkoB joined
04:52 osa1 joined
04:52 insitu joined
04:52 <MarcelineVQ> Which actually sounds like a real fun direction to take
04:53 <thimoteus> until you program yourself out of a job
04:55 <dyreshark> that's why you have to write buggy code. then you're paid to maintain the code that replaced you
04:56 <dfeuer> Better: come up with new ideas later to improve what you did before.
04:56 <dfeuer> Or to improve *other* things in valuable ways.
04:58 <jle`> freeside: that's something you have to learn how to live with on your own terms
04:58 <dfeuer> If an employer is short-sighted and wants to get rid of the programmers as soon as "the job is done", then there's not much point trying to work for them, is there?
04:58 <freeside> https://emilschutte.com/stackoverflow-autocomplete/
04:59 Itkovian joined
05:00 carlosda1 joined
05:01 noam_ joined
05:02 Shatnerz0 joined
05:05 indi_ joined
05:07 rcschm joined
05:10 rcschm joined
05:10 jgt4 joined
05:12 takle joined
05:13 nick123 joined
05:13 splanch joined
05:14 bhiliyam joined
05:15 dmwit_ joined
05:18 dec0n joined
05:19 takle joined
05:27 monochrom joined
05:27 Swizec joined
05:30 revprez_atlanta joined
05:31 danvet joined
05:34 changsen111 joined
05:37 nick123 joined
05:38 mstruebing joined
05:38 <iqubic> So no one has a tutorial on mutable data???
05:38 <iqubic> Actually I just fouind a few by searching.
05:39 akegalj joined
05:39 biglambda joined
05:39 caumeslasal joined
05:41 <jle`> the magic of google
05:43 <kadoban> A tutorial on mutable data is so general, not even sure what that'd encompass :-/
05:48 johnw_ joined
05:51 <MarcelineVQ> jle`: these dependent type posts are quite fun, makes "if it compiles it's correct" considerably less of a hyperbole, any plans for your part 3? :>
05:52 changsen111 joined
05:52 alexbiehl joined
05:55 changsen111 joined
05:57 albel727 joined
05:57 efge joined
05:57 Argue__ joined
05:58 mavihs joined
05:58 mavihs joined
06:03 tomku joined
06:04 <jle`> MarcelineVQ: part 3 has been stalling because i haven't thought of enough things to put into it to make it worth its own part, heh
06:04 <jle`> but part 3 was always intended to be the conclusion :)
06:04 <jle`> glad you enjoyed it!
06:04 Swizec joined
06:05 zeroed joined
06:06 ogrady joined
06:07 grumble joined
06:07 <MarcelineVQ> I feel I'll be referring back to it a few times for my next project, atm I'm doing the exercises at the end of part 2 and am finding the compiler help to be more pleasant than expected. also finally managed to have a use for <=< for one of these which I envision using a lot more from now on
06:09 eatman_ joined
06:09 iqubic joined
06:09 <iqubic> How good is Haskell's concurrency support?
06:10 <Axman6> it's the best
06:10 <peddie> iqubic: absolutely fantastic
06:10 <MarcelineVQ> pretty good, it's one of ghc' selling features
06:10 <Axman6> (honestly)
06:11 <iqubic> How does concurrent Haskell work?
06:11 <iqubic> Anyone got a tutorial on that?
06:11 <MarcelineVQ> iqubic: here's the ideal resource for all of that http://chimera.labs.oreilly.com/books/1230000000929/index.html
06:11 <Axman6> you can fire up 100,000 threads for 100,000 connections and not have to worry too much. lots of really good tools and primitives for dealing with concurrency randing from IORefs which are excellent if you have a single shared resource, through to software transactional memory, which is world leading AFAIC
06:12 <iqubic> How good is this book: http://chimera.labs.oreilly.com/books/1230000000929?
06:13 <iqubic> The entire thing is online, for me to read and look at.
06:13 <Axman6> it's excellent
06:13 <adelbertc> iqubic: its good
06:13 <iqubic> Should I read through it?
06:13 <iqubic> I can get started on that now.
06:13 <adelbertc> yep
06:13 <adelbertc> iqubic: do you have experience with Haskell already?
06:13 <Axman6> it was written by Simon Marlow, who is responsible writing many of the tools which are discussed in the book, there's basically no better resource
06:13 Lokathor_ joined
06:14 <cocreature> iqubic: you might want to skip the parallel part and focus on the second chapter if you are interested in concurrency
06:14 <iqubic> adelbertc: Plenty of Haskell experience already.
06:14 <cocreature> at least I found that significantly more useful
06:14 <adelbertc> then yeah go for it
06:14 hurkan joined
06:14 <iqubic> cocreature: I should do that.
06:14 hexfive joined
06:15 <iqubic> I assume that I can read the two halves in any order.
06:15 <Axman6> iqubic: how much Haskell experience? I wouldn've thought that 'plenty' would include having seen how to di concurrency already :)
06:15 bhiliyam joined
06:15 <cocreature> yep they are completely independent iirc
06:15 takle joined
06:15 <MarcelineVQ> iqubic: best to read each half in order, but yes they can be read seperately for sure
06:15 <MarcelineVQ> *the contents of each half
06:15 <Axman6> \I believe the contents of each chapter build on earlier topics, but parallelism and concurrency are pretty orthogonal
06:16 <iqubic> MarcelineVQ: I will start with the concurrent half first.
06:16 <Axman6> at least as far as GHC is concerned
06:16 raichoo joined
06:16 <cocreature> the concurrency chapter also contains the best explanation of exceptions in Haskell that I’ve seen
06:16 <iqubic> But I will read the first chapter of the concurrent section befor the second chapter of the concurrent section.
06:16 <MarcelineVQ> chapter 2 is worth reading even if one doesn't care about concurrency or parallelism
06:16 <iqubic> I don't understand Haskell exceptions at all.
06:16 <cocreature> iqubic: one more reason to read that book :)
06:17 <iqubic> MarcelineVQ: What is the title of chapter 2?
06:17 <MarcelineVQ> at least, the first section of it "Lazy Evaluation and Weak Head Normal Form" http://chimera.labs.oreilly.com/books/1230000000929/ch02.html
06:18 <Axman6> iqubic: just read the whole thing, it's not very long
06:18 yellowj joined
06:19 <iqubic> I know what WHNF is and what a Thunk is.
06:19 <iqubic> Do I still need to learn about the eval monad?
06:20 thatguy joined
06:20 MoALTz joined
06:20 <MarcelineVQ> Only if you want to learn about parallelism, that first section is all I wanted to draw your attention to
06:21 <iqubic> What is the first section? WHNF and Thunks?
06:21 <Axman6> iqubic: we can't tell you what you need to know, figure that out for yourself, quit trying to take shortcuts :\
06:22 <Axman6> all this time asking and you could be 1/10th into the book already ;)
06:22 <MarcelineVQ> yeah
06:22 <Axman6> it;'s not a big book, just read it
06:22 takle joined
06:22 <MarcelineVQ> yeah to your question I mean :>
06:23 Salih joined
06:23 zeroed joined
06:23 zeroed joined
06:24 Micamo joined
06:28 Sose joined
06:29 edvorg joined
06:29 {emptyset} joined
06:31 quchen joined
06:33 dfordivam joined
06:34 eacameron joined
06:40 infinity0 joined
06:40 eazar001 joined
06:41 jgt joined
06:42 castlelore joined
06:42 <jgt> is there a practical difference between `i :: Int; i = 10` and `i = 10 :: Int`?
06:43 <jgt> (using semicolon there to denote a newline)
06:43 <Axman6> the latter will cause warnings from things like hlint about there being no type signature for i, but afaict that's about it
06:44 mszczygiel joined
06:44 takuan joined
06:44 <cocreature> it will even cause a GHC warning with -Wall which is probably more important than an hlint warning
06:44 <jgt> hlint isn't warning me about it, which doesn't sound right…
06:45 <cocreature> maybe it doesn’t warn about things that GHC already warns you about?
06:45 <jgt> and I have `ghc-options: -Wall -fwarn-tabs -O2` in the cabal file
06:45 acidjnk22 joined
06:45 <cocreature> jgt: is that a top-level binding?
06:45 <kadoban> The former is more idiomatic probably. And for more complicated I think the latter can mean different things. Like I suspect that i = 10 :: Num a => a might have a different meaning than expected sometimes (right?)
06:45 eacameron joined
06:46 <kadoban> Or at least a different meaning than the i :: version would
06:46 <cocreature> kadoban: at least in a let binding with the monomorphism restriction enabled that should behave differently
06:46 <jgt> cocreature: yes, top-level binding
06:46 <jgt> and yes, GHC warns about it
06:46 <cocreature> ah ok
06:46 <jgt> so that's a definite answer to the question
06:46 <jgt> thanks folks! :)
06:47 shoopaloop joined
06:49 Rodya_ joined
06:50 laz joined
06:50 eacamero_ joined
06:51 detrumi joined
06:51 dlight joined
06:52 zero_byte joined
06:53 guiben joined
06:57 eacameron joined
06:57 dylukes joined
07:00 <iqubic> Threads are really cool in Haskell. I love the forkIO function.
07:01 <joe9> how do I get the seconds :: Integer from the NominalDiffTime? toInteger does not workr.
07:01 <joe9> http://codepad.org/m5wj5kiW
07:02 carlosda1 joined
07:02 thc202 joined
07:02 Wizek joined
07:02 Wizek_ joined
07:03 <cocreature> joe9: how about floor . realToFrac?
07:03 <joe9> got it ((floor :: Double -> Integer) . realToFrac ) :: NominalDiffTime -> Integer
07:03 <joe9> Thanks cocreature
07:03 <Axman6> does round now just do it?
07:03 <Axman6> not*
07:03 <Axman6> or floor?
07:04 <cocreature> oh yeah floor is sufficient
07:04 eacameron joined
07:04 t0by joined
07:05 <joe9> How about the other way from Double -> MkNominalDiffTime . There does not seem to be a fracToReal
07:06 flohsor joined
07:07 MrWoohoo joined
07:07 merijn joined
07:09 shayan_ joined
07:09 <cocreature> joe9: does realToFrac not work?
07:09 <cocreature> it seems like it should
07:10 guiben joined
07:10 <joe9> cocreature: yes, it did.
07:10 <joe9> h
07:10 <joe9> cocreature: I was thinking that tehre must be a fracToReal for that.
07:11 guiben joined
07:11 <cocreature> joe9: Double is an instance of Real and NominalDiffTime is an instance of Fractional
07:11 vlatkoB_ joined
07:11 <cocreature> but they are also both instances of the other class so you can use it in both directions
07:12 slomo joined
07:12 slomo joined
07:12 <joe9> cocreature: oh, ok. Thanks.
07:12 eacameron joined
07:12 Wizek__ joined
07:16 bhiliyam joined
07:18 TheLemonMan joined
07:19 eacameron joined
07:20 __paul0 joined
07:20 wroathe joined
07:21 ubsan_ joined
07:22 vydd joined
07:26 raichoo joined
07:26 mtesseract joined
07:28 seveg joined
07:28 cur8or joined
07:30 eacameron joined
07:33 recycletrash joined
07:37 recyclet_ joined
07:38 lithie joined
07:39 dga joined
07:40 piyush-kurur joined
07:40 govg joined
07:42 baldrick joined
07:42 recycletrash joined
07:43 jeltsch joined
07:46 eacameron joined
07:48 vydd joined
07:49 Sh4rPEYE joined
07:50 johnw_ joined
07:50 Rodya_ joined
07:50 hamishmack joined
07:51 <Sh4rPEYE> Hello. How do I write a general listcomp for n lists, that looks similar to this: [x ++ y | x <- xs, y <- ys]
07:51 <Sh4rPEYE> I tried to do it somehow with map, but withou luck
07:51 ventonegro joined
07:51 <quchen> listcomp?
07:51 <quchen> general?
07:51 <Cale> Are you looking for sequence?
07:51 <Cale> > sequence [[1,2,3],[4,5],[6,7,8]]
07:51 <lambdabot> [[1,4,6],[1,4,7],[1,4,8],[1,5,6],[1,5,7],[1,5,8],[2,4,6],[2,4,7],[2,4,8],[2,...
07:52 <Sh4rPEYE> It seems
07:52 <Sh4rPEYE> Thanks!
07:52 <Sh4rPEYE> I'll look up the source of it :-)
07:53 Sgeo joined
07:53 eacameron joined
07:55 <quchen> sequence (xs:xss) = do { x <- xs; xs' <- sequence xss; pure (x:xs') }
07:56 <dfordivam> > isJust Nothing
07:56 <lambdabot> False
07:56 <dfordivam> Wow nice!
07:57 gregman_ joined
07:57 <merijn> isJust is an awful function which should be avoided
07:57 xificurC joined
07:58 <dfordivam> merijn: in what context?
07:58 biglambda joined
07:58 <jle`> dfordivam: in almost every context
07:58 takle joined
07:58 <merijn> ^^ that
07:58 quchen joined
07:59 <quchen> isJust is a perfectly valid projection onto Bool
07:59 <quchen> fromJust is the devil
07:59 _sras_ joined
07:59 kazagistar joined
07:59 <merijn> quchen: But booleans are also evil and should be avoided! :)
07:59 <_sras_> When I try to run ghc-mod on a file I get this error "hGetContents: invalid argument (invalid byte sequence)". How can I fix this?
07:59 <jle`> i prefer (()<$) for my projections to Bool
07:59 <merijn> _sras_: Step 1) check whether your locale/terminal is set up correctly
08:00 <quchen> merijn: Haha
08:00 <merijn> If you play with your booleans too much you'll go blind
08:01 <quchen> Necessary evil sometimes though.
08:01 <quchen> e.g. filter
08:01 <_sras_> merijn: That was it.
08:01 <jle`> code smell, at least
08:01 <_sras_> Thankyou.
08:01 <jle`> especially for someone new to haskell, 97% of bool usage is unnecessary
08:01 MoALTz joined
08:02 eacameron joined
08:02 <merijn> _sras_: I have noticed a suspicious amount of broken default locale/terminal settings on linux, so it's my goto intuition ;)
08:02 <jle`> quchen: the solution is to not use filter and just use mapMaybe :)
08:02 sepp2k joined
08:02 mmn80 joined
08:02 <mniip> hey quchen!
08:02 <dfordivam> I actually never use isJust, mainly do applicative...
08:02 carlosda1 joined
08:02 marfoldi joined
08:03 splanch joined
08:03 <mniip> 1491674340 [20:59:00] <mniip> has anyone ever thought about using Löb for an assembler? 1491674350 [20:59:10] <mniip> and/or linker 1491674374 [20:59:34] <mniip> e.g, say the branch instruction has multiple encodings depending on the size of the operand 1491674399 [20:59:59] <mniip> and the operand is the location of the invocation target, which ultimately depends on the size of the instructions inbetween
08:03 <jle`> you can also pattern match, too
08:03 <Philonous> case isJust foo of False -> ... *cough*
08:03 <jle`> reminds me of everyone's favorite
08:03 <dfordivam> omg
08:03 <_sras_> merijn: So hGetContents trying to read the file in a wrong encoding, right?
08:04 <jle`> foo xs | not (null xs) = f (head xs)
08:04 biglama joined
08:04 <jle`> case isJust foo of True -> ... fromJust foo ...
08:04 <MarcelineVQ> jle`: if pred then True else False
08:04 <jle`> MarcelineVQ: if pred == True then True else False
08:05 <merijn> _sras_: All the String versions of file access (such as hGetContents in base) guess the encoding from the locale, but if the file is a different encoding, then decoding to unicode fails and it errors, yeah
08:05 <mniip> map f xs = bool [] (f (head xs) : map f (tail xs)) (null xs)
08:05 <MarcelineVQ> :>
08:05 <jle`> scary though that code like that would be perfectly normal/routine in other languages
08:06 <jle`> that's why if not (null xs) then ... head xs ... pops up so much
08:06 <merijn> _sras_: You can also override the default encoding to read with (or, probably better: use the ByteString file operations with an explicit decode)
08:06 <jle`> people are just used to doing it
08:06 <mniip> well
08:06 <jle`> in other languages
08:06 <mniip> to be fair, it isn't too slow either
08:06 hamishmack joined
08:06 <mniip> if not, null, and head are inlined
08:06 <mniip> and head's other branch is eliminated as dead
08:06 <jle`> the performance is probably the least problematic thing about that, heh
08:06 <mniip> and the head binding is floated out
08:06 <_sras_> merijn: Yes
08:07 richi235 joined
08:07 <jle`> mniip: performance in general isn't too bad if everything was inlined all the way :)
08:08 <mniip> you can't inline everything
08:08 <merijn> has anyone ever proposed aliasing ByteString to Bytes?
08:08 jgertm joined
08:08 <jle`> inline `find (/= 1) (map collatz [1..]`
08:08 <jle`> O(1) solution to the collatz conjecture ~
08:08 <jle`> er, `find ((/= 1) . collatz) [1..]`
08:08 <mniip> merijn, and String to Unicode?
08:08 <merijn> I don't think we're getting rid of the type completely, for backwards compatibility, but we could improve things a little bit
08:09 Yuras joined
08:09 <merijn> mniip: String is fine, I think
08:09 <jle`> let ghc inline 100% and the resulting program is O(1)
08:09 <tdammers> in fact "unicode" is a bit of a shitty name, because it's kind of an implementation detail
08:09 <merijn> jle`: Not really
08:09 eacameron joined
08:09 <mniip> jle`, not really
08:09 <Philonous> Would be better if String was a synonym for Text, but that would break too much code
08:09 <merijn> jle`: Input dependent computation
08:09 <mniip> it's either O(1) or O(inf)
08:10 <mniip> I can't tell you which right now
08:10 <quchen> mniip: I did not think about Löb for years.
08:10 <quchen> I don’t think it’s very practical, but fairly cute ;-)
08:10 <mniip> quchen, I was messing with assembly the other day and it just randomly kicked in
08:10 <jle`> mniip: well, if the conjecture is false, no program will ever get compiled
08:10 <mniip> like, I've read the lob article once
08:11 <mniip> jle`, not true
08:11 <mniip> it will compile to a bottom
08:11 <Philonous> tdammers, "Unicode" specifies the set of allowed elements, isn't that exactly what the type should say?
08:11 nick123 joined
08:11 <mniip> jle`, dead code elimination
08:11 OnkelTem joined
08:11 <jle`> oh, um, s/false/true
08:12 <quchen> mniip: Should you find something out let me know :-)
08:12 markus1189 joined
08:12 <mniip> quchen, not sure there's anything to find out
08:12 YellowOnion joined
08:12 <mniip> just writing a huge program for the purpose of testing out a trick
08:12 dcoutts joined
08:13 markus1199 joined
08:15 revprez_atlanta joined
08:15 filterfish joined
08:15 eacameron joined
08:15 <tdammers> Philonous: my philosophy is that the name should signal conceptual meaning, a.k.a. functional intent
08:15 <YellowOnion> anyone familiar with Lens? can I make `for producer (\x -> Pipes.Zlib.decompress width (yield x)) >-> consumer` less ugly?
08:16 <YellowOnion> sorry not lens pipes
08:16 <tdammers> if you use a different encoding for your strings, and change the compiler to support it, then the conceptual meaning of your program doesn't change, but calling your strings "unicode" is now incorrect
08:16 tremon joined
08:16 bhiliyam joined
08:16 <tdammers> even though the program itself is still the same
08:17 <merijn> tdammers: That's not true
08:17 indi_ joined
08:17 <merijn> tdammers: unicode is not an encoding
08:17 <Philonous> tdammers, Unicode doesn't imply an encoding, just the set of elements, no? It would be different if the type was called "UTF-8"
08:17 <merijn> tdammers: It's an abstract representation that GHC uses, unicode is encoded to specific encodings, but isn't one
08:17 <tdammers> Philonous: yes, but you could make up a character set that isn't a subset of unicode
08:17 <tdammers> merijn: I know
08:17 lep-delete joined
08:18 <tdammers> merijn: "enoding" was the wrong word
08:18 <merijn> tdammers: You'd deserve to be executed, revived, and subsequently executed again for that crime against humanity >.<
08:18 <tdammers> merijn: sure sure
08:18 <tdammers> but, anyway
08:18 <tdammers> while unicode isn't an encoding, the mapping of code points to integer indexes is an implementation detail
08:18 <quchen> Good gracious, what did tdammers do?
08:19 <tdammers> quchen: I suggested creating a character set that is not a subset of unicode
08:20 <MarcelineVQ> the ultimate sin
08:20 vydd joined
08:20 <merijn> Oh, wait, I forgot, GHC has DerivingLift now :D
08:21 <tdammers> it's a thought experiment, I'm not suggesting you actually do it
08:21 eacameron joined
08:21 mekeor joined
08:21 <Philonous> tdammers, You could do that, but that would be a different type with different semantics. I don't see why it would be sensible to give it the same name
08:21 <tdammers> I'm just saying that even though there is only one true way of mapping integers to characters, ahem, code points, doesn't magically stop that mapping from being an implementation detail
08:22 atomi joined
08:23 <tdammers> what I'm interested in when I write "String" is that it's a sequence of character-like things. not necessarily that those character-like things are actual unicode code points, or that their mapping to integer ordinals is done according to unicode
08:24 zeroed joined
08:24 <merijn> Honestly String will never be proper anyway
08:24 <tdammers> how so
08:24 <merijn> Text is...ok, but for actual proper unicode support you'll need text-icu
08:24 <merijn> tdammers: Many operations are broken according to unicode semantics
08:25 <Philonous> tdammers, Sounds like you're describing a type-class rather than a type.
08:25 <merijn> For example "toUpper :: Char -> Char" is a plain lie
08:25 eacamero_ joined
08:26 mattyw joined
08:26 eklavya joined
08:26 <tdammers> toUpper :: a -> a -- is impossible anyway, unless the locale is somehow encoded in a itself
08:26 <tdammers> (cf. Turkish)
08:26 <merijn> tdammers: GHC uses system locale
08:26 <merijn> But String screws even that up
08:26 <tdammers> and even then, it would have to be a -> Maybe a
08:26 <tdammers> (cf. German)
08:27 <tdammers> let's see, what else breaks
08:27 <tdammers> modifiers obviously
08:27 <halogenandtoast> If one were to try and assign a color to Haskell (ruby is red, python green, etc.) What would that color be? I assume either Purple or Orange.
08:27 <MarcelineVQ> purps
08:27 ozgura joined
08:27 <tdammers> purpange or orgle
08:28 <merijn> > toUpper 'ffl'
08:28 <lambdabot> '\64260'
08:28 nick_h joined
08:28 <merijn> > text [toUpper 'ffl']
08:28 <lambdabot>
08:28 <merijn> > T.toUpper $ T.pack ['ffl']
08:28 <lambdabot> "FFL"
08:30 <merijn> But yeah, you need text-icu for dealing with things like Turkish
08:30 <Rembane> ick: Not bringing in dependent types is a very good thing. :)
08:30 wroathe joined
08:31 zar joined
08:31 <halogenandtoast> thanks
08:33 <quchen> Dependent types in Haskell feels a bit like Java users trying to use lambdas.
08:33 <Rembane> ick: Or if you change your mind, try Idris or Agda. They are cool.
08:33 <Rembane> quchen: Awkward?
08:33 <gallais> quchen: https://stepik.org/course/ThCS-Introduction-to-programming-with-dependent-types-in-Scala-2294/
08:34 <quchen> gallais: Oh, you’re also on #haskell!
08:34 <quchen> Rembane: Not awkward, it’s doable and everything, but it doesn’t really fit.
08:34 <quchen> The syntax is clumsy, you hit walls left and right
08:34 <quchen> Then you bolt on fixes to make the walls softer
08:35 <quchen> gallais: Let me finish that one way of writing dependent types first, then I’ll head over to doing it in Scala ;-)
08:37 <merijn> Is there a way to silence a single orphan instance warning?
08:37 <quchen> Nope
08:37 <merijn> crud
08:37 <quchen> Put it into its own module :-)
08:37 <merijn> quchen: That would make things really inconvenient
08:38 <quchen> https://github.com/quchen/stgi/blob/master/test/Testsuite/Test/Orphans.hs
08:38 <quchen> That’s what I always do
08:38 <merijn> quchen: See, that's the quitters approach
08:39 <merijn> Real men just decide to add a PRAGMA to GHC to toggle individual orphan warnings and solve the issue once and for all!
08:39 <quchen> Quite the opposite: it allowed me to continue with more important problems
08:39 <* quchen> is not a real man :-(
08:39 <merijn> quchen: Sometimes progress has to be sacrificed for the greater good!
08:39 <merijn> (The greater good!)
08:39 <quchen> (The greater good!)
08:40 <Iceland_jack> (crusty jugglers)
08:40 xtreak joined
08:41 <merijn> quchen: I believe in the compound awesomeness of small incremental improvements :)
08:41 freusque joined
08:41 ziarkaen joined
08:42 lattenwald joined
08:44 oish joined
08:44 Argue__ joined
08:47 <Rembane> merijn: And human sacrifice?
08:48 <merijn> Rembane: I don't admit to that in public ;)
08:48 <Rembane> merijn: :D
08:50 <* Iceland_jack> exchanges nervous glances
08:50 <* Iceland_jack> is human
08:51 Rodya_ joined
08:51 marr joined
08:51 <* Rembane> hands Iceland_jack a I'm-not-a-human-hat.
08:52 <* Iceland_jack> dons hat
08:52 <Iceland_jack> *beep*
08:52 xtreak joined
08:53 delYsid joined
08:54 locallycompact joined
08:54 <Rembane> :D
08:55 <Rembane> I miss the "this package has changed"-announcements in this channel.
08:56 <peddie> Rembane: me too; where did that go? it was a fun way to discover new packages
08:58 <quchen> That was Hackagebot
08:58 <peddie> what happened to Hackagebot?
08:58 Croniamental joined
09:00 <quchen> I don’t know
09:02 mbuf joined
09:02 <Rembane> It seems like the maintainer didn't want to maintain it anymore for some reason. https://mail.haskell.org/pipermail/haskell-cafe/2016-December/125859.html
09:03 carlosda1 joined
09:04 <peddie> I guess it probably was a bit noisy at times . . .
09:04 <quchen> I muted Hackagebot too.
09:04 <quchen> But announcing major version bumps would be fine.
09:04 <quchen> Problem was lots of pushes of x.x.x.FOO versions.
09:04 merijn joined
09:05 <quchen> In other words, I would like to have a feed of new packages or notable updates, and not everything.
09:05 Sh4rPEYE joined
09:05 <Rembane> Let it post at most once every fiften minutes and aggregate all the updates in between. And don't let the same package be seen more than once per 24hrs.
09:06 cfricke joined
09:06 sanitypassing joined
09:06 <quchen> Yup, that sounds good to me.
09:07 ragepandemic joined
09:08 sanitypassing joined
09:13 gregman_ left
09:14 takle joined
09:14 <quchen> Haskell has functions from type to type, for example Maybe. What (exactly) is the difference to type families here?
09:15 <quchen> Type constructors are closed and injective, yes, but that’s not enough.
09:15 <Iceland_jack> Maybe is matchable (injective + generative)
09:15 skeuomorf joined
09:15 <quchen> Type constructors also create a new type when applied, whereas type families can be closed and injective
09:15 <quchen> … and still not be type constructors
09:16 <quchen> »Generative« sounds good. What does it mean exactly?
09:16 fizruk joined
09:16 <Iceland_jack> f a ~ g b ==> f ~ g
09:16 <quchen> That’s injectivity.
09:16 <Iceland_jack> no
09:16 <quchen> Oh, no.
09:16 <quchen> Wait. Right.
09:17 <quchen> Coinjectivity? :-)
09:17 <Iceland_jack> (f a ~ f b ==> a ~ b) is injectivity
09:17 <Iceland_jack> together they form... MATCHABILITY
09:17 <LiaoTao> Matchability, it's our hero
09:17 bhiliyam joined
09:17 <quchen> Shouldn’t it be forall a. (f a ~ g a) -> f ~ g?
09:17 <quchen> Why a and b?
09:18 Kreest__ joined
09:19 <Iceland_jack> Because it generates a new type, what ever the arguments are is my understanding
09:19 <hexagoxel> because generative does not imply injective, i suppose?
09:20 glamas joined
09:20 <quchen> So it’s ∀ a b f g. f a ~ g b => f ~ g
09:22 locallycompact joined
09:22 <Iceland_jack> I believe matchability will be visible in future Haskell (DependentHaskell)
09:22 <Iceland_jack> with an optional tick on the arrow '->
09:23 oisdk joined
09:23 insitu joined
09:29 dhil joined
09:30 ziocroc joined
09:30 Argue_ joined
09:31 eacameron joined
09:33 niko joined
09:34 mkoenig joined
09:34 ebzzry joined
09:37 eacameron joined
09:47 eacameron joined
09:47 ogrady_ joined
09:50 takuan joined
09:50 fakenerd joined
09:51 Rodya_ joined
09:52 ogrady joined
09:54 <adarqui> hey what's the status on records having fields with the same names? i remember something coming in to ghc8.. records can have the same field names, as long as the code typechecks, or something
09:54 bbee joined
09:56 troydm joined
09:57 ziyourenxiang joined
09:59 Darwin226 joined
10:00 <lieven> DuplicateRecordFields is in 8.mumble
10:00 <adarqui> ah cool that's what it was called, thanks
10:01 filterfish joined
10:02 Gurkenglas joined
10:02 mnaqii joined
10:02 filterfish_ joined
10:04 Guest10294 joined
10:04 Sh4rPEYE joined
10:04 <Guest10294> hey guys i'm an object oriented language and i'm here to pwn u all
10:05 <Ferdirand> hello. Would you like to hear how you can use object-oriented patterns in Haskell through the use of co-algebraic style ?
10:05 <Guest10294> u like that?
10:06 <Guest10294> speak.
10:06 <tdammers> object-oriented programming can be very useful
10:06 <tdammers> the hammer principle still applies though
10:08 <quchen> (Hammer as in hammer factory factory, yes)
10:09 danthemy_ joined
10:09 <Iceland_jack> Guest10294: Hey welcome to #haskell
10:09 <Ferdirand> Guest10294: it's nothing fancy, really. Since functions are first-class values in Haskell, it is very easy to make objects as datastructures that contains the actual operations that you would call on an object
10:11 freusque joined
10:13 <Guest10294> i object
10:14 <Iceland_jack> I hope that's a pun :)
10:14 Neo joined
10:14 <Iceland_jack> Have you taken a look at Haskell before?
10:15 Kreest_ joined
10:16 binaryplease joined
10:18 bhiliyam joined
10:18 twanvl joined
10:18 <tsahyt> Is there a library providing a type such as Set (cardinality :: Nat) a?
10:19 shayan_ joined
10:20 Icewing joined
10:20 <tsahyt> I'm asking purely out of curiosity. There are of course several libraries for length indexed vectors and lists, so I was wondering whether we also have something analogous for sets
10:20 bbee joined
10:20 <Iceland_jack> tsahyt: It would be more difficult
10:22 <Iceland_jack> consing an element to a length-indexed vector increments its length, but inserting an element into a set.. well: it depends on the Eq/Ord constraint
10:22 <tsahyt> I suppose you could do something like insert :: a -> Set n a -> Either (Set n a) (Set (S n) a)
10:23 <Iceland_jack> That's right
10:23 <tsahyt> alternatively, require a proof that the element is not already a member of the set
10:23 <tsahyt> which I suppose would be much harder
10:26 <tsahyt> Iceland_jack: from an API standpoint, would member :: a -> Set (S n) -> Bool be preferable to allowing checks against the empty set?
10:26 <tsahyt> Set (S n) a that is
10:27 robotroll joined
10:27 <Iceland_jack> What is that preventing? It moves the proof obligation to the user of the function
10:28 <tsahyt> agreed, checking membership in the empty set is a perfectly valid thing to do anyhow
10:28 zhigang1992 joined
10:28 <tsahyt> I'm just going through Data.Set and thinking about what explicit cardinality would buy me
10:28 <Iceland_jack> When you enter this territory Liquid Haskell feels like a better direction
10:29 <tsahyt> dunno, for vectors at least vector-sized is quite nice to use and compiles to efficient code too. and I get more information out of typed holes
10:29 <Iceland_jack> It allows modeling type level sets, you could have an insertion function that only inserts new elements (as an example)
10:30 <tsahyt> I still have to dig deeper into liquid haskell. first I'm gonna finish this idris book though, while trying to port as many ideas over to somewhat sane haskell code as possible. purely as an exercise to see what is possible and what isn't.
10:30 fiddlerwoaroof joined
10:31 <Guest10294> guys
10:31 <Guest10294> tried writing hello world with haskell
10:31 ragepanda joined
10:31 <Guest10294> see u on the other side
10:32 <quchen> tsahyt: You’d need an existential to get the resulting set, insert : a -> Set n a -> ∃ i. Set (n + i) a or something
10:32 <Iceland_jack> quchen: It hides a bit too much, it only needs one bit of information
10:32 <Guest10294> try writing hello world with haskell
10:32 <tsahyt> quchen: I think I prefer the either approach here
10:33 <quchen> Either is an existential boolean ;-)
10:33 <quchen> Either a b = ∃ x. if x then a else b
10:33 <Iceland_jack> Why use either when you can be complicated: a -> Set n a -> ∃b. Set (if b then n else n + 1)
10:34 <tsahyt> quchen: on the topic of existential results, what's the sanest way to encode this anyhow? I've usually been using some version of specialized existential wrapper for this. Then there's also data Some (x :: k -> *) = forall a. Some (x a)
10:34 <Iceland_jack> Guest10294: How did writing hello world go?
10:34 <quchen> tsahyt: I think it’s pretty hard to write this in Haskell (and make it usable)
10:34 <quchen> Heck, I think this is pretty hard to write in general!
10:34 rockfordal joined
10:35 <tsahyt> hmm. I might give this a shot. just writing this sort of wrapper around Data.Set, and then see how to use it
10:35 <Iceland_jack> go for it tsahyt
10:35 <Guest10294> try writing hello world in haskell
10:35 <quchen> A wrapper sounds like a good start.
10:35 <Iceland_jack> if it turns out useful, make a package ;)
10:35 <Iceland_jack> Guest10294: main = putStrLn "Halló heimur!"
10:35 <tsahyt> Iceland_jack: if I actually end up doing it, I might. It'd probably strip a lot of functions from the underlying implementation though
10:36 seveg joined
10:36 medicijnman joined
10:36 recycletrash joined
10:36 <tsahyt> quchen: it's something I've come to appreciate about vector-sized. It doesn't actually prove much to the compiler itself but rather just wraps around ordinary vectors. but in turn you get a very efficient implementation with guarantees on top. The main downside is really that because they're vectors, you can't pattern match on them.
10:37 LuckyRawApe_ joined
10:37 netheranthem joined
10:38 <Guest10294> i mean, try writing hello world 5 times in haskell
10:38 <Iceland_jack> main = do putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"
10:39 <quchen> main = go 5; go 0 = pure (); go n = putStrLn "hello world" >> go (n - 1)
10:39 eklavya joined
10:39 <quchen> main = traverse putStrLn (replicate 5 "hello world")
10:39 inkbottle joined
10:39 Gloomy joined
10:39 <quchen> main = replicateM_ 5 (putStrLn "hello world")
10:39 <Iceland_jack> main = replicateM (putStrLn "Halló heimur!")
10:39 <Iceland_jack> oops, _ 5 :)
10:40 <Guest10294> main = do putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"; putStrLn "Halló heimur!"
10:40 <quchen> main = fix (\rec n -> if n > 0 then putStrLn "hello world" >> rec (n-1) else pure ()) 5
10:40 rcschm joined
10:40 <quchen> One more and we’ve written 5 5-helloworlds. :-)
10:41 <Iceland_jack> #haskell: ahead of schedule!
10:42 <quchen> A pity main has to have (IO a), otherwise we could recurse on it directly.
10:43 <Guest10294> quchen: haha told ya
10:43 <quchen> n = unsafePerformIO (newIORef 5); main = do { x <- readIORef n; modifyIORef' (subtract 1) n; if n > 0 then putStrLn "hello world" >> main else pure () }
10:44 Yuras joined
10:44 edvorg joined
10:44 sternenseemann joined
10:44 <sternenseemann> Data.Sequence (from containers) is lazy, right?
10:44 <quchen> I think it has a strict spine
10:45 <Iceland_jack> main = putStr $ take 60 $ cycle "hello world\n"
10:45 <sternenseemann> quchen: what exactly do you mean by that?
10:45 <quchen> The elements are lazy, but the data structure itself is strict
10:45 <quchen> So you can’t have an infinite Seq for example
10:45 <sternenseemann> i see
10:46 <quchen> Just like Data.Map
10:46 <sternenseemann> mh
10:47 albertid joined
10:47 <sternenseemann> annoying though, because a) our project tries to not use lazy data structures and b) I will evaluate all elements, always
10:48 <sternenseemann> oh nvm
10:48 <Taneb> sternenseemann, is there any particular reason you're avoiding laziness?
10:48 <sternenseemann> I can solve it much better using map
10:48 <sternenseemann> Taneb: space/memory leaks, I am told
10:48 wroathe joined
10:48 <Taneb> sternenseemann, I think that's made out to be more of a problem than it is
10:48 <quchen> Not having laziness causes time leaks.
10:51 <Athas> If you want to avoid laziness out of principle, Haskell may be the wrong language.
10:51 <pacak> In some situations you need laziness, in some - you want things to be strict. Deciding when you want which behavior is hard.
10:51 zar joined
10:53 phaji_ joined
10:54 augur joined
10:54 <Guest10294> putStrLn ; putStrLn ; putStrLn ; putStrLn ; putStrLn looks pretty sequential
10:54 <Guest10294> u just got pwned
10:54 pzel joined
10:55 <quchen> kek
10:55 <Iceland_jack> Guest10294: You can replace the semicolon with an operator!
10:55 <Iceland_jack> putStrLn "hello" *> putStrLn "hello" *> putStrLn "hello" *> putStrLn "hello" *> putStrLn "hello"
10:55 <Iceland_jack> much functional wow
10:55 <quchen> sternenseemann: Avoiding laziness is not a good idea in general, consider »head [1..10^100]«.
10:56 <quchen> sternenseemann: Learning when to have or when to avoid laziness is very useful; I don’t think avoiding it at all cost is a good default.
10:56 <quchen> For example, I’d say there’s nothing wrong with having the values lazy in a sequence.
10:57 <quchen> But you can wrap the library and force all values before inserting them into the sequence of course.
10:57 <quchen> Data.Map does this: .Lazy does not force, .Strict forces values before insertion.
10:57 <quchen> The actual Map data structure is identical (and hence compatible) in both cases.
10:58 RegEchse joined
11:00 anuxivm joined
11:01 <Athas> quchen: which means that e.g. the Functor instance doesn't force, right?
11:02 Philonous left
11:04 Iceland_jack joined
11:05 carlosda1 joined
11:06 mmn80 joined
11:06 bennofs joined
11:11 <tdammers> yeah, the strict/lazy thing with Map (and HashMap) is actually somewhat annoying sometimes
11:12 <tdammers> operation on maps that go through typeclasses don't know anything about whether you want lazy or not
11:13 <tdammers> newtyping the base map type to a strict and a lazy flavor would have been nicer IMO
11:13 <merijn> tdammers: But then you have to reimplement every function :)
11:13 thillux joined
11:13 <tdammers> GeneralizedNewtypeDeriving to the rescue
11:14 <merijn> tdammers: That doesn't derive functions, just classes
11:14 <tdammers> oh sure
11:14 <tdammers> the functions, you want most of them to be different though, don't you?
11:15 rcat joined
11:15 <merijn> tdammers: I don't think so?
11:15 <tdammers> or maybe not
11:15 <merijn> tdammers: Everything that deals with splitting/combining maps can stay identical
11:15 <tdammers> hmm, but you could implement that stuff for the base type, then forwarding it to the newtype wrappers shouldn't be tricky at all
11:15 <tdammers> I do ssee the appeal though
11:16 <Athas> merijn: that kind of duplication is OK in a library.
11:16 <merijn> Athas: It's painful to implement, though
11:16 <Athas> Of course, if Haskell had a proper module system we wouldn't have this issue!
11:16 <merijn> Maybe you could automate it with TH...
11:16 <tdammers> also, I think it'd be justify to pull out the TH hammer here, or maybe even CPP
11:16 <tdammers> s/justify/justified/g
11:17 <Athas> Wouldn't TH require that you write the entire library as an AST?
11:17 <merijn> Athas: No, I meant write TH to convert from lazy map to strict
11:17 <merijn> Most function can be converted in a fairly straightforward manner, just make all occurences of the content of the map strict
11:17 carlosda1 joined
11:18 ysahil joined
11:18 <tdammers> that, or write TH that attempts to write the functions for any given type, and call it once on the strict and once on the lazy newtype
11:18 oisdk joined
11:19 <tdammers> or just use CPP to paste the same code into both modules
11:19 bhiliyam joined
11:19 tdfirth joined
11:21 lambda2348327432 joined
11:22 bjz joined
11:23 <lambda2348327432> Someone has an idea why it says duplicate declaration here? https://codepaste.net/bc61ka
11:24 <Gurkenglas> lambda2348327432, you wrote sumeveryTwo instead of sumEveryTwo once
11:24 <lambda2348327432> lol
11:24 <Gurkenglas> (So the line above and below that count as separate declarations)
11:24 jgt joined
11:24 <lambda2348327432> why the hell does it tell me the declaration is duplicate then?
11:24 <Gurkenglas> See my last line
11:25 darlan joined
11:25 <Gurkenglas> sumEveryTwo = map sum . chunksOf 2
11:25 wroathe joined
11:25 <lambda2348327432> well it should rather complain about the definition being non exhausive because one case is missing?
11:26 nagyf joined
11:26 <Gurkenglas> Turn on -Wall, though I'm not sure that'll show you anything while there are still duplicate declarations
11:26 recycletrash joined
11:27 <Athas> Sometimes GHC will not show warnings if there is an error.
11:27 <Athas> (Although nowadays, I think that is rare.)
11:29 <lambda2348327432> but why does it complain about multiple declarations in the first place? the two declarations cover different parameters
11:29 <Gurkenglas> They're not right next to each other, there's something else between them
11:29 <lambda2348327432> Oh oka, did not know this mattered
11:32 plutoniix joined
11:33 ysahil joined
11:34 ziocroc joined
11:35 wroathe joined
11:35 Philonous joined
11:41 cur8or joined
11:41 CoderPuppy joined
11:42 fakenerd joined
11:42 ozgura joined
11:44 lstor joined
11:44 psychicist__ joined
11:45 seveg joined
11:45 freusque joined
11:48 ragepandemic joined
11:49 <lambda2348327432> in a list comprehension i can use if...else like this: [if even x then x else 0 | x <- [1..10]]. but can i also use guards here like [x | even x = 2 * x | otherwise 0 | x <- [1..10]]?
11:50 <lambda2348327432> probably will confuse the parser
11:50 emc2 joined
11:51 Yuras joined
11:52 freusque joined
11:54 eacameron joined
11:54 edvorg joined
11:55 jgt joined
11:56 <merijn> lambda2348327432: Not like that, no
11:56 acarrico joined
11:56 <lyxia> what you wrote first is the simplest, but if you want to filter and keep only even numbers you can write [x | x <- [1..10], even x]
11:56 <sternenseemann> quchen: I totally agree, but that's the policy I guess
11:56 <Iceland_jack> lambda2348327432: you can bind it with a "let" but that just shuffles the if/then/else it about
11:56 <Iceland_jack> -it
11:56 <sternenseemann> quchen: we also sometimes have lazy data structures
11:57 <sternenseemann> quchen: if one accesses all elements of a finite data structures, laziness might be not the best idea generally e. g.
11:58 <quchen> Yes, if you always need all element of a data structure laziness is useless.
11:59 sanett joined
11:59 <quchen> Well, may be useless.
12:00 wroathe joined
12:00 eacameron joined
12:00 jeltsch joined
12:04 <pacak> quchen: If you produce those elements on demand and consume incrementally laziness will reduce max memory requirement.
12:04 fizbin joined
12:05 Gloomy joined
12:05 biglambda joined
12:05 <Jinxit> i have some very repetitive code, any ideas for how i can make it less repetitive? http://lpaste.net/5161123845821693952
12:05 <Jinxit> the instance declarations, that is
12:05 yhhko joined
12:06 <Jinxit> (just realized there's a type error in there but it's less important)
12:06 augur joined
12:06 revprez_atlanta joined
12:06 insitu joined
12:07 <xificurC> is there a way to write (-2) and mean a section and not unary negation? Or does one need to write \x -> x - 2
12:07 <Iceland_jack> :t subtract 2
12:07 <lambdabot> Num a => a -> a
12:07 nbro joined
12:08 <nbro> hi
12:08 <Iceland_jack> > subtract 2 10
12:08 <lambdabot> 8
12:08 <Iceland_jack> Hello nbro
12:08 <nbro> .
12:08 <yhhko> > (-) 3 2
12:08 <xificurC> Iceland_jack: thanks
12:08 <lambdabot> 1
12:08 <xificurC> yhhko: (-) won't work since I need x-2 not 2-x
12:09 <nbro> is there a way to suggest corrections in the Haskell wiki?
12:09 <yhhko> ah gotcha :)
12:09 pzel joined
12:09 <yhhko> best i can do is "flip (-) 2" then :)
12:09 romildo joined
12:09 ziocroc joined
12:10 <Iceland_jack> subtract = flip (-) ;)
12:10 <pacak> Jinxit: It might help to extract recursion part... http://blog.callcc.name/posts/free-sourcepos.html - something along those lines
12:10 fizbin joined
12:10 <romildo> Which library should I use to read the contents of a HTML _local_ file?
12:11 dhil joined
12:11 <Jinxit> pacak: i'll go read that, thanks
12:11 <pacak> romildo: tagsoup?
12:12 <quchen> pacak: Hence the »may be« correction :-þ
12:12 <quchen> > 10 `subtract` 2
12:13 <lambdabot> -8
12:13 <quchen> :)
12:14 <pacak> Jinxit: It might be not exactly your case but I successfully used this approach to save a bunch of typing for various AST manipulations.
12:14 <romildo> pacak, yes, I am going to use tagsoup. But how to read the content of the HTML file before giving it to tagsoup? The examples uses Network.HTTP. I was thinking that would be something simpler for that.
12:15 eacameron joined
12:15 <pacak> Hmmm....
12:15 <pacak> :t readFile
12:15 <lambdabot> FilePath -> IO String
12:16 SimpleL joined
12:16 <Jinxit> pacak: the problem with this approach is that it assumes all AST nodes refer to other AST nodes
12:16 <pacak> > ((!!2) . iterate pred) 10
12:16 <lambdabot> 8
12:16 <Jinxit> my entire AST type is a tree itself
12:17 ClaudiusMaximus joined
12:17 <Jinxit> to enforce some correctness in the type system itself
12:17 wroathe joined
12:17 marvin3 joined
12:17 <pacak> Looks more like a list then..
12:18 Wuzzy joined
12:19 <yhhko> > (+(-2)) 10
12:19 <lambdabot> 8
12:19 <yhhko> xificurC: is that what you were looking for?
12:19 <Jinxit> well, a Func is a TypeDef, a Maybe (TypeDef), a few MemberDeclarations, and an Annotation. a TypeDef is either a BuiltIn, a UserType, or an Array. this keeps going down the levels
12:19 <Jinxit> how is that a list?
12:19 bhiliyam joined
12:19 <xificurC> > subtract 2 10
12:19 <lambdabot> 8
12:20 <xificurC> yhhko: as Iceland_jack pointed out
12:20 <yhhko> yeah but that uses letters. who wants letters.
12:20 <xificurC> yhhko: the result is the same, sure
12:20 <Iceland_jack> @let (.-) = flip (-)
12:20 <lambdabot> Defined.
12:20 <Iceland_jack> > 2 .- 10
12:20 danthemyth joined
12:20 <lambdabot> 8
12:21 <yhhko> > let subtract_two x = x-2 in subtract_two 10
12:21 <lambdabot> 8
12:21 <xificurC> yeah, many ways to make it *less* readable :)
12:21 augur joined
12:22 <yhhko> perhaps i should've called it "subtract_smallest_prime_integer"
12:22 tabaqui1 joined
12:22 eacameron joined
12:23 amx joined
12:24 <pacak> > appEndo (foldMap Endo (replicate 2 pred)) 10
12:24 <lambdabot> 8
12:25 <Iceland_jack> oh boy..
12:25 Itkovian joined
12:25 <Iceland_jack> That's horribly difficult to understand, let me fix it
12:25 <Iceland_jack> > foldMap Endo (replicate 2 pred) `appEndo` 10
12:26 <lambdabot> 8
12:26 <Iceland_jack> there we go
12:26 <yhhko> > (*2) . pred . (/2) $ 10 -- *prays*
12:26 <lambdabot> 8.0
12:26 <orion> :t pred
12:26 <lambdabot> Enum a => a -> a
12:26 <Iceland_jack> > fold [Endo pred, Endo pred] `appEndo` 10
12:26 <lambdabot> 8
12:27 wroathe joined
12:27 romildo left
12:28 <pacak> > let here_be_kittens = appEndo . foldMap Endo . flip replicate pred in here_be_kittens 2 10
12:28 <lambdabot> 8
12:29 asmyers joined
12:29 nh2 joined
12:30 recycletrash joined
12:30 ogrady joined
12:30 ClaudiusMaximus joined
12:30 _sg joined
12:32 danthemyth joined
12:32 xormor joined
12:32 jaspervdj joined
12:32 <xormor> I am willing to learn Haskell! I visited the WWW page for it.
12:33 <xormor> how do I get started? have an URL or advice?
12:34 <pacak> http://learnyouahaskell.com/chapters - nice beginner friendly book
12:34 unK_ joined
12:35 jgertm joined
12:35 <cocreature> xormor: do you already know other programming languages? maybe even functional programming languages?
12:36 mstruebing joined
12:37 biglambda joined
12:37 ogrady joined
12:38 Claudius1aximus joined
12:38 ziocroc joined
12:41 mpsag joined
12:41 JuanDaugherty joined
12:41 magneticduck joined
12:42 thatguy joined
12:43 AntiSpamMeta joined
12:45 des_ joined
12:45 ico joined
12:45 <maerwald> pacak: please no
12:46 <maerwald> lyah is not very popular here
12:46 <maerwald> @where learnhaskell
12:46 <lambdabot> https://github.com/bitemyapp/learnhaskell
12:46 <maerwald> go there
12:46 <xormor> cocreature, C, C++ and assembly (x86 and amd64). I mostly know the '90's versions of the C and the C++ programming languages. I learned a bit of Java earlier, but have forgotten since.
12:47 al-damiri joined
12:47 <JuanDaugherty> it's not?
12:47 <JuanDaugherty> (lyah)
12:47 <xormor> cocreature, I have forgotten BASICA and QBasic.
12:48 <nbro> hey
12:48 <nbro> what would be the purpose of doing "main = do return"
12:48 <nbro> i.e. just doing "return"
12:49 <* JuanDaugherty> is ready to fall in with the party line, once reeducated.
12:49 Saizan joined
12:49 <alanz> it would have to be "main = do return ()", and it's basically a NOP
12:50 <cocreature> xormor: if you already know programming, http://haskellbook.com/ is supposed to be very good (but I haven’t read it personally since it came out after I’ve learned Haskell)
12:51 nick123 joined
12:51 merijn joined
12:51 <cocreature> nbro: it might be worth noting that "do x" is always the same as "x"
12:52 <cocreature> x doesn’t even need to be a monadic action
12:52 <cocreature> > do 'a'
12:52 <lambdabot> 'a'
12:52 <Myrl-saki> cocreature: Scarily.
12:53 nomicflux joined
12:53 danza joined
12:53 <cocreature> Myrl-saki: hm I think I’ve gotten used to it my now. it doesn’t seem scary anymore ;)
12:53 <cocreature> but yeah it’s definitely slightly confusing
12:53 dsh joined
12:53 Rodya_ joined
12:54 <Myrl-saki> Petition to rewrite `do x` as `return () >> x`
12:54 <Myrl-saki> :D
12:54 <nbro> alanz: because I saw a similar expression, i.e. without () in front of return, and that’s why I was wondering if it meant something special
12:54 <nbro> return indeed requires an argument
12:55 <nbro> so it would make sense to simply "do return", unless return would also be defined somewhere else
12:55 <nbro> *it wouldn’t
12:55 <alanz> yes
12:55 <cocreature> > (do return) ()
12:55 <lambdabot> error:
12:55 <lambdabot> • Ambiguous type variable ‘m0’ arising from a use of ‘show_M244744301726...
12:55 <lambdabot> prevents the constraint ‘(Show (m0 ()))’ from being solved.
12:55 <cocreature> that would work :)
12:55 <alanz> but sometimes you would use "return ()" as a parameter in a call to a function expecting another function
12:56 <xificurC> @let ret = do return
12:56 <lambdabot> Defined.
12:56 <nbro> I heard that >=> is the monadiac composition operator
12:56 <nbro> "> = > "
12:56 <pacak> :t (>=>)
12:56 <nbro> in practice, what does it mean?
12:56 <lambdabot> Monad m => (a -> m b) -> (b -> m c) -> a -> m c
12:56 <cocreature> :t (.)
12:56 <nbro> it takes two functions
12:56 <lambdabot> (b -> c) -> (a -> b) -> a -> c
12:56 eklavya joined
12:56 <pacak> Same idea
12:56 <nbro> it’s like monads are transitive
12:56 <pacak> takes output from one computation shoves it into second one
12:57 <pacak> @src (>=>)
12:57 <lambdabot> Source not found. Have you considered trying to match wits with a rutabaga?
12:57 <pacak> lambdabot: :-P
12:57 <Myrl-saki> >=> is an emoticon
12:57 gawen joined
12:57 <nbro> I’m asking, in pratice, does anyone use this operator?
12:57 <merijn> I do
12:57 <Myrl-saki> nbro: Yes.
12:57 <pacak> I do
12:57 <tdammers> absolutely
12:57 <Myrl-saki> lmao
12:57 <alanz> I used it for the first time for real recently
12:57 <cocreature> there is also <=<
12:57 <nbro> can I see a concrete example where it’s really useful
12:57 <merijn> Fish operator is amazing
12:57 <Myrl-saki> cocreature: When you want to look the other way.
12:57 <nbro> ?
12:57 <merijn> nbro: xml-conduit docs
12:58 <cocreature> :t (<=<)
12:58 <lambdabot> Monad m => (b -> m c) -> (a -> m b) -> a -> m c
12:58 <cocreature> :t (>=>)
12:58 <lambdabot> Monad m => (a -> m b) -> (b -> m c) -> a -> m c
12:58 <cocreature> the former is closer to (.)
12:58 <Myrl-saki> Now we only need ^=^ and v=v
12:58 <cocreature> Myrl-saki: we already have ^+^
12:58 <nbro> (.)
12:58 <nbro> lol
12:58 <cocreature> I don’t think I’ve seen ^=^
12:58 <Myrl-saki> :t (^+^)
12:58 <lambdabot> error:
12:58 <lambdabot> • Variable not in scope: ^+^
12:58 <lambdabot> • Perhaps you meant ‘^^’ (imported from Prelude)
12:58 <merijn> nbro: also: https://gist.github.com/merijn/d8188ddd129718ffcfb0#file-scraper-hs-L56-L59
12:58 <Myrl-saki> Awww. :C
12:58 <pacak> con :: Handle -> Enumerator [RawPacket] IO a
12:58 <cocreature> Myrl-saki: it’s in linear
12:58 <pacak> con infoSock = enumTcpHandle infoSock >=> liveWooriSimDriver proto infoSock
12:58 <alanz> nbro: see https://github.com/ghc/ghc/commit/5282bb1772ba3f1dc999a177965e543822f342a0
12:58 <pacak> ^ from a real project
12:59 <cocreature> Myrl-saki: https://hackage.haskell.org/package/linear-1.20.5/docs/Linear-Vector.html#v:-94--43--94-
12:59 <alanz> makes the mapM simpler, else you need a separate function or complex lambda
12:59 <Myrl-saki> cocreature: Thanks.
12:59 sdothum joined
12:59 <cocreature> surprisingly hoogle doesn’t know ^=^
13:00 <Myrl-saki> cocreature: hayoo?
13:00 <cocreature> doesn’t find anything either
13:00 <nbro> so, in layman’s terms, how would you describe the utility of this operator?
13:00 <Myrl-saki> nbro: "I need to use (.), but I only have monads"
13:01 <Myrl-saki> s/need/want/
13:01 cpennington joined
13:01 <alanz> nbro: it lets you write "f (g x)" where both f and g are monadic
13:01 <cocreature> f <=< g = \x -> f =<< (g x)
13:01 <xormor> Haskell is a good-looking language. Maybe I should try drinking coffee while learning Haskell. I might have to go buy some milk from the grocery store first :-D
13:01 <alanz> so it means "do f after g, on the result"
13:02 <nbro> Myrl-saki: what if one doesn’t know about (.)
13:02 <cocreature> nbro: I think then it makes sense to introduce (.) first :)
13:02 <nbro> xormor: ahah
13:02 <nbro> good-looking it a nice measure to spend time loving
13:02 <nbro> lol
13:02 indi_ joined
13:03 <nbro> *metric?
13:03 <Myrl-saki> nbro: Teach them about (.)
13:03 <nbro> > (.)
13:03 <Myrl-saki> :D
13:03 <lambdabot> error:
13:03 <lambdabot> • No instance for (Typeable b0)
13:03 <lambdabot> arising from a use of ‘show_M675969288210474283411652’
13:03 <nbro> oh
13:03 <pacak> @src (.)
13:03 <lambdabot> (f . g) x = f (g x)
13:03 <nbro> never mind
13:04 <nbro> lol
13:04 <nbro> I was not thinking about .
13:04 <* Iceland_jack> is still in love with the definition of (.)
13:04 azahi joined
13:04 <nbro> but you were just wrapping it with ( and )
13:04 <nbro> lol
13:04 <nbro> ok
13:04 cpennington joined
13:04 <cocreature> nbro: you need to wrap operators in parenthesis if you want to use them in a non-infix way
13:04 <cocreature> which includes things like :t
13:05 TheLemonMan joined
13:05 <nbro> @todo something
13:05 <lambdabot> @todo has no args, try @todo-add or @list todo
13:05 <cocreature> lambdabots definition of (.) would prevent GHC from inlining (.)!
13:05 <Iceland_jack> :t (+)
13:05 <lambdabot> Num a => a -> a -> a
13:05 <nbro> cocreature: yeah, right, I was imply not visualizing (.) in my head as the operator "composition of functions"
13:05 takle joined
13:06 <Iceland_jack> > (+) 10 200
13:06 <lambdabot> 210
13:06 <nbro> imply=*simply
13:06 <nbro> *deferencing
13:06 <nbro> lol
13:06 <nbro> dereferencing
13:06 <nbro> omg
13:06 <nbro> > [1..10]
13:06 <lambdabot> [1,2,3,4,5,6,7,8,9,10]
13:07 <nbro> lol
13:07 <nbro> @seen
13:07 <lambdabot> Say again?
13:07 ptek joined
13:07 <Myrl-saki> * is dereferencing.
13:07 <Myrl-saki> :P
13:07 <nbro> I meant, when you dereference simply you get imply
13:08 <nbro> I almost laugh in the 9th dimension of this multidimensional existence
13:08 <nbro> *laughed
13:08 <xificurC> anyone used haskell for web scraping with some tips on what lib to use?
13:08 <nbro> @free
13:08 <lambdabot> Try `free <ident>` or `free <ident> :: <type>`
13:08 <cocreature> xificurC: I just use http-conduit & html/xml-conduit
13:08 <nbro> @dummy
13:08 <lambdabot> dummy
13:09 <nbro> @dice
13:09 <lambdabot> unexpected end of input: expecting number, "d" or "("
13:09 <cocreature> xificurC: merijn has a gist of scraping cartoon images somewhere iirc
13:09 fizruk joined
13:09 <nbro> @undo
13:09 <lambdabot> Error: expected a Haskell expression or declaration
13:09 <cocreature> nbro: you can send private messages to lambdabot instead of spamming here
13:09 <Myrl-saki> @dice d
13:09 <lambdabot> unexpected end of input: expecting number
13:09 <nbro> @search "blah"
13:09 <lambdabot> Unknown command, try @list
13:09 <merijn> cocreature: I just linked it, but it's bitrotted
13:09 markus1199 joined
13:10 <nbro> cocreature: I know and I should at least lie and tell you I’m not doing it on purpose
13:10 <Myrl-saki> merijn: owo hi hi~
13:10 <merijn> It relies on the Monad instance of Async, for one
13:10 augur joined
13:10 <pacak> @dice 1d20
13:10 <lambdabot> pacak: 10
13:10 <nbro> but my me of the 7th dimension is ruining me
13:10 <merijn> xificurC: But see here: https://gist.github.com/merijn/d8188ddd129718ffcfb0
13:11 <cocreature> I guess bringing it up2date shouldn’t be terribly hard
13:11 <merijn> cocreature: Well, depends on your definition of bringing it up to date
13:11 <cocreature> merijn: getting it working with a new version of async :)
13:11 <merijn> cocreature: async dropped the monad instance of Concurrently, so it's actually impossible with modern async
13:12 iAmerikan joined
13:12 <cocreature> merijn: well you can just manually implement concurrency
13:12 <merijn> But the scraping part should work
13:12 bjz_ joined
13:13 ystael joined
13:13 laz joined
13:13 <merijn> bleh, now I need to benchmark criterion >.>
13:13 <nbro> endofunctor
13:13 <merijn> To see if my changes broke things >.<
13:14 <nbro> and functor from a category to itself
13:14 <merijn> oh, semi-relatedly...
13:14 <nbro> clearly
13:14 <merijn> What's the cheapest semaphore like operation I can do in GHC?
13:15 <merijn> Like...if I need synchronisation cheaper than MVars how fast can I get?
13:16 <quchen> atomicallyModifyIORef?
13:16 <quchen> Very small semaphore
13:16 <nbro> so arrows in category theory are like a generalization of linear maps for vector spaces
13:16 <quchen> But I think it outperforms MVars. But don’t quote me on that.
13:17 <merijn> quchen: Makes it hard to block until time X, though...
13:17 <merijn> Now I need to benchmark semaphore-ish operation so I can write my actual benchmark >.>
13:17 <nbro> what’s a "groupoid"?
13:17 <nbro> well, it depends on how you read it
13:17 <nbro> :D
13:19 medicijnman joined
13:19 <quchen> merijn: How about atomicModifyIORef?
13:19 <quchen> It’s like »withMVar with a () lock«
13:20 <quchen> If you really need an n-lock, i.e. a semaphore, then I’m not sure what to use but Data.Sem
13:20 <quchen> Or whatever the standard Foo.Concurrent semaphores are called
13:20 bhiliyam joined
13:20 <fizbin> Can someone explain the difference between http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Strict.html#v:modify-39- and http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Lazy.html#v:modify-39- ?
13:20 <merijn> quchen: Yeah, but those seem fairly expensive compared to the operations I wanna benchmark >.>
13:20 <merijn> fizbin: One is for Strict State, the other for Lazy?
13:21 <quchen> »Seem«?
13:21 <fizbin> But look at the description of modify'
13:21 mtesseract joined
13:21 <merijn> quchen: Well, I'm trying to benchmark writeChan, which is basically 2 MVar operations :)
13:21 flohsor joined
13:22 <fizbin> Specifically, is modify' the same as modify when working in C.M.State.Strict ?
13:22 <cocreature> fizbin: strict vs lazy state monad does not mean strictness in the state value
13:22 bodisiw joined
13:22 <cocreature> fizbin: the lazy statemonad does a lazy pattern match on the tuple
13:23 <cocreature> fizbin: https://hackage.haskell.org/package/transformers- vs https://hackage.haskell.org/package/transformers-
13:23 <fizbin> Which "the tuple"?
13:23 crobbins joined
13:23 nick123 joined
13:23 <cocreature> State is a function s -> (a, s)
13:23 <ski> monochrom has some examples of lazy `State', iirc
13:23 mattyw joined
13:24 <cocreature> https://kseo.github.io/posts/2016-12-28-lazy-vs-strict-state-monad.html also has some examples
13:26 <merijn> Quick question: If I have 'x :: a' and 'f :: a -> IO b' what's the best way to ensure the function is fully evaluated (without executing the IO)? "let !act = f x in ..."?
13:27 zar joined
13:27 ysahil joined
13:27 <fizbin> So I'm still a bit confused then (even after reading that) about what C.M.State.Strict is actually strict in.
13:28 <ski> fizbin : see "control.monad.state.lazy" by monochrom in 2010-11-25 at <http://lpaste.net/41790>
13:29 <ski> fizbin : "lazy ST example" by ibid in 2012-02-18 at <http://lpaste.net/63925> might also be interesting
13:29 BlueRavenGT joined
13:29 <quchen> State m >>= f = State (\s' -> let (x1,s1) = runState m s; (x2,s2) = runState (f x1) s1 in (x2,s2))
13:29 <quchen> State m >>= f = State (\s' -> let ~(x1,s1) = runState m s; ~(x2,s2) = runState (f x1) s1 in (x2,s2))
13:29 <quchen> Lazy vs strict state.
13:30 emc2 joined
13:30 <quchen> Probably full of typos. Anyway, the irrefutable pattern (the tilde) is the difference between strict and lazy state.
13:30 <fizbin> quchen: Right, I can read the definitions. I'm just having trouble figuring out what that means for what gets evaluated.
13:30 <fizbin> And when.
13:31 <quchen> To be *sure* see the STGi ;-)
13:32 <quchen> In the lazy case with the tildes, you get the final result, (x2,s2) without evaluating the runState computations
13:33 <quchen> They’re forced only when pattern-matching on the tuple
13:33 arw joined
13:33 <quchen> Well, what you get is »the result«. And matching »the result« will give you (x2,s2), and in the process force the entire thing.
13:33 math493 joined
13:33 <merijn> oh...I guess I can just seq my IO action?
13:34 cpup joined
13:34 <quchen> Sure
13:34 ryantrinkle joined
13:34 <fizbin> It seems that it's the rough equivalent of "strict state will evaluate your do expression stack roughly similar to the way you expect an imperative language to behave, whereas lazy state will behave the way it would if you remember that it's all haskell functions really and seemingly infinite tail recursion can be fine if you don't stare into the abyss"
13:34 <merijn> That's probably simpler than messing with NFData
13:34 <merijn> Since I don't think IO has an NFData instance
13:34 <merijn> oh, wait, I guess I want pseq
13:35 <merijn> since seq doesn't guarantee ordering
13:36 chlong joined
13:36 <quchen> If you’re in IO anyway, you can use »evaluate x«.
13:36 <quchen> :t evaluate
13:36 <lambdabot> a -> IO a
13:36 <quchen> »IO-seq«
13:36 <fizbin> However, evaluating functions in your "do" list or (>>=) chain is distinct from actually evaluating state.
13:36 <ski> `evaluate' is for the result of an `IO' action. it seemed merijn wasn't in such a situation ?
13:36 clamchowder left
13:37 <quchen> Evaluate takes any thunk as argument.
13:37 <math493> Can anyone here construct a simple (not too sophisticated) example showing the power of functional programming? Something where you can see the power of Haskell compared to e.g. Python? I am trying to learn what functional programming is, but none of the examples I have seen so far couldn't be done in Python (even though I was adviced not to use a multi-paradigm language for functional programming). Preferably no more than 5 lines
13:37 eschnett joined
13:37 mizu_no_oto_work joined
13:37 <math493> I heard that there are some things which you could not just have used Python for (or which would be very ugly or cumbersome in Python).
13:37 <quchen> evaluate x = x `seq` pure x (almost)
13:37 <merijn> ski: I'm in IO and have 'x :: a', 'f :: a -> IO b' and want to evaluate the application 'f x', specifically to ensure that, if 'x' is not used inside 'f' it can be GCed directly instead of being kept live by the thunk
13:37 <Iceland_jack> math493: honestly, you will never see the power of it from one, two or thirty examples
13:38 <quchen> math493: How would you show the power of OOP in maybe 5 lines?
13:38 <math493> quchen: Well, from what I understand, OOP is a lot more... verbose.
13:39 <math493> Iceland_jack: So it is impossible to show some nice (and uncomplicated) example illustrating what functional programming is and why it is nice?
13:39 <quchen> Well, give it 50 lines.
13:39 <quchen> The point is, single examples don’t tell you much.
13:39 <Iceland_jack> it's about building a vocabulary and seeing powerful pattern emerging from that, to someone not familiar with those patterns they will seem trivial and boring
13:39 <ski> quchen : "almost", yea. it's not quite that
13:39 augur joined
13:39 <quchen> ski: The docs give the details, yes
13:39 doomlord joined
13:39 <Iceland_jack> math493: Not in any way that has real substance
13:40 <ski> merijn : *nod*
13:40 <quchen> math493: Seeing how you know OOP already, consider how often you’re playing the »where is the actual work happening« game. Or the »is this initialized correctly«. Or the »in what state am I and may I do this«.
13:40 <ski> ("run-time compilation", perhaps)
13:40 <math493> quchen: Yeah :)
13:40 <quchen> FP avoids these problems for the most part: mutable/implicit state is minimal if present at all, and usually there’s a very clear picture of what you have.
13:40 des_ joined
13:40 <merijn> ski: It's just unclear how I can best accomplish that, since I'm not sure "let !act = f x in ..." works and cobbling something together with seq is kinda tricky
13:41 <math493> But OK, if I allow more than 10 lines, could you then come up with an example? Again, please try to keep it simple, so it is easy to understand (or at least, if it is complicated, please explain it to me) :)
13:41 mattyw joined
13:41 <quchen> Scopes are very small: maybe 2-3 variables. There is no »wait this global variable might be false so …«
13:41 <quchen> math493: Well, you’ve seen the map-and-filter examples. That’s as far as 10 lines get you.
13:42 <merijn> math493: You already know 1 or more other languages, right?
13:42 <math493> merijn: Yes. But no functional programming language.
13:42 <merijn> math493: What's the hardest issue you encounter finding/preventing/fixing bugs?
13:42 jgertm joined
13:42 <ski> merijn : initially i thought you had already considered something like `let y = f x in seq y (..y..)', and considered it not pretty enough ..
13:42 <math493> merijn: Well, it depends, I would say. But sometimes finding the right part...
13:43 <ski> (hence `let !y = f x in ..y..' instead)
13:43 <merijn> ski: That doesn't actually do what I need, though :)
13:43 <ski> oh ?
13:43 _101010 joined
13:43 <merijn> ski: Since it's not guaranteed the left hand of 'seq' is forced before the right hand
13:43 <merijn> The order of 'seq' is unspecified
13:43 <ski> oh, right. s/seq/pseq/ then
13:44 <math493> But let me try to phrase my question in another way: I guess people in #haskell like Haskell. Why do you like Haskell? What are the advantages of Haskell compared to e.g. Python? Why don't you use Python instead?
13:44 <math493> I guess it has some strengths :)
13:45 <quchen> It’s easier to reason about programs, so I don’t have to think as much. :-)
13:45 <Sornaensis> haskell is easier to test and refactor than python
13:45 <quchen> Data point: we don’t have debuggers. We sometimes want debuggers, but not very often.
13:45 RoyalNightGuard joined
13:45 <quchen> Debugging Haskell mostly means reading the code, as opposed to running it and seeing where it crashes.
13:46 <_101010> Hello everyone! Sorry if it's a real stupid question, but do I need cabal separately if I install stack? I can't get SublimeText3 to work with stack.
13:46 <math493> :)
13:46 <quchen> This is because individual parts are usually small and understandable.
13:46 <Sornaensis> you can use ghci for limited debugging
13:46 <quchen> _101010: No, you do not need Cabal to install Stack.
13:46 <Sornaensis> it's not usually necessary
13:46 eacameron joined
13:46 <quchen> I don’t know the Sublime plugin though, maybe it’s not written to be compatible with stack? :-/
13:47 <_101010> It's this, https://github.com/SublimeHaskell/SublimeHaskell
13:47 <merijn> math493: I would say "finding the right part" is usually difficult, because usually some part of the state of your program is not what you expect it to be, but it's hard to track where it changed
13:47 <_101010> It mentions stack, but also mentions cabal. I thought stack is all I need. Maybe I am wrong
13:48 <math493> merijn: I agree.
13:48 <merijn> math493: Pure functional program reduces where and how state can get changed, thus making it easier to think about your program
13:48 sanett joined
13:49 piyush-kurur joined
13:49 <quchen> math493: Data point. I’ve made breaking core changes to codebases with ~10% test coverage without serious problems. In Python this would be completely impossible.
13:49 gcross_ joined
13:49 <math493> quchen: Hm, sounds cool :)
13:50 <quchen> Haskell generally relies on making illegal states unrepresentable in your program. Python takes the approach to test all programs whether they contain no illegal states.
13:50 <merijn> Data point about Python: 10 times in the past two days I've ran a script, waited over 15 minutes for results to get computed and...all I get was a stack trace and a "variable not defined" message
13:50 <quchen> The difference is that a test is easy to forget, but a compiler verification is not.
13:50 <lpaste> merijn pasted “No title” at http://lpaste.net/7791473864998912000
13:50 <merijn> ski: That's what I'm going with atm
13:51 seveg joined
13:52 <merijn> ski, quchen: Think there's anything I missed?
13:52 <quchen> math493: Even more importantly, some people believe tests are for wuzzies that don’t know how to code. If you come across a codebase without any tests, you’d much rather have that in Haskell than in Python ;-)
13:52 <quchen> (That said, those people are dangerously incompetent. Even in Haskell.)
13:52 mattyw joined
13:52 <merijn> quchen: :(
13:52 <quchen> (That said, they exist anyway.)
13:52 <quchen> merijn: Hm?
13:52 <Sornaensis> cowboy codin'
13:53 <merijn> quchen: You're calling me dangerously incompetent!
13:53 <quchen> merijn: Am I?
13:53 <* quchen> gets his pitchfork to hunt merijn
13:53 <merijn> I only write tests for my GHC patches :p
13:53 <quchen> Sounds like you’re writing tests.
13:54 <merijn> Not for my non-GHC code :p
13:54 sdothum joined
13:54 <quchen> Don’t ruin it.
13:54 <quchen> :-s
13:54 <ski> merijn : `x' corresponding to `env' and `i' ?
13:54 Rodya_ joined
13:54 <merijn> ski: Yeah
13:54 <quchen> I even write tests in Agda, so the »type system handles this for me« does not count.
13:55 <quchen> test3 = 3 + 5 == 8; test3 = _
13:55 <quchen> :-)
13:55 <merijn> quchen: I don't even write tests for a lot of my non-Haskell code! :p
13:55 <tsahyt> it's impossible to use Data.Set.map to get from a non-empty set to an empty set, isn't it?
13:55 <c_wraith> Sometimes I write tests. Like to ensure that there isn't a space leak in my anticipated use pattern.
13:55 <tsahyt> the smallest set you can create with it should be a singleton set
13:55 <tsahyt> given that the input is non-empty of course
13:56 <c_wraith> tsahyt: seems right to me
13:56 <tsahyt> good
13:56 <tsahyt> thanks
13:56 <ski> merijn : hm, perhaps use `finally' rather than `onException' (and the extra `clean')
13:56 <tsahyt> some parts of Data.Set turn out to be very hard to wrap into a cardinality indexed type. map, filter, partition, etc.
13:56 ysahil joined
13:57 <tsahyt> anything that can do pretty much arbitrary changes to the cardinality
13:57 fkurkowski joined
13:57 <merijn> ski: This is just copying the implementation of bracket
13:57 <tsahyt> as well as union and friends
13:57 <tsahyt> but a set module without union feels very incomplete
13:57 <merijn> ski: Could probabyl simplify it if it works, yes
13:57 sw1nn joined
13:58 <c_wraith> tsahyt: this is related to why Data.Set doesn't have a Functor instance.
13:58 <quchen> merijn: I admire people that don’t need tests, as long as I don’t have to touch their code or use their software. But the ability to hammer out 30ksloc without tests and get something that does *anything* is amazing.
13:58 <tsahyt> c_wraith: there's also mapMonotonic though. but that's rather unsafe
13:59 <JuanDaugherty> dangerously incompetent ftw, the armada is on it's way
13:59 <merijn> quchen: Only up to 13k so far ;)
14:00 <tsahyt> on the plus side I got some mileage out of the additional type parameter for all the findMin etc functions, which turn out to actually be partial in Data.Set
14:00 augur joined
14:00 rotty_ joined
14:01 IndigoTiger joined
14:01 <xificurC> how does one turn on pragmas in a running ghci session?
14:02 <c_wraith> xificurC: for language extensions, use :set -XExtensionName
14:02 <c_wraith> xificurC: for other pragmas.. They don't really make that much sense in ghci anyway, do they?
14:03 Nicmavr joined
14:04 <c_wraith> (I might be forgetting about something that does make sense in ghci but isn't a language pragma)
14:04 <joe9> any jhc users here? heard that it's code is easy to understand and I want to learn the internals.
14:04 josef641 joined
14:05 herzog_ernst joined
14:06 fakenerd joined
14:06 <xificurC> c_wraith: thanks
14:06 bab joined
14:08 <dfeuer> tsahyt: there are now total versions of those.
14:09 <dfeuer> If I'm not very much mistaken.
14:11 <tsahyt> dfeuer: looks like deleteFindMin and deleteFindMax do not have a total version
14:11 <tsahyt> I can only see lookupMin and lookupMax that return Maybe
14:12 <dfeuer> tsahyt: https://hackage.haskell.org/package/containers-
14:12 ziocroc joined
14:12 <tsahyt> oh right
14:13 danthemyth joined
14:13 harfangk joined
14:13 <tsahyt> I should pay more attention. I even ended up wrapping those too, not even realizing that they do the same thing but safely
14:15 <shapr> everybody seen https://github.com/IntelLabs/flrc ?
14:16 ChristopherBurg joined
14:17 augur joined
14:17 `^_^v joined
14:18 <tsahyt> I guess the best that I can do for union is existential quantification with bounds on the cardinality
14:18 simukis_ joined
14:18 `^_^v joined
14:19 sanett_ joined
14:19 coltfred joined
14:20 asmyers joined
14:21 <c_wraith> shapr: is that the one they promised to open source many years ago?
14:21 meck joined
14:21 bhiliyam joined
14:22 Aruro joined
14:23 sdothum joined
14:23 <shapr> c_wraith: yup, research papers were published from 2012 - 2013
14:24 <c_wraith> I'm glad it finally was released.
14:24 <c_wraith> also, it looks like a backend to GHC, meaning it should handle anything GHC can (at least for supported versions of GHC..)?
14:26 <shapr> yeah, their own intermediate representation -> pillar and mlton in there somewhere
14:27 burtons joined
14:27 eatman joined
14:27 <joe9> shapr: is it easier to port?
14:27 cyborg-one joined
14:28 <c_wraith> doubt it.
14:28 <c_wraith> I mean, it needs ghc as a front-end
14:28 <joe9> makes sense.
14:28 <c_wraith> So you can skip the registerized backend, but you still need a haskell compiler to bootstrap the whole thing
14:28 <joe9> c_wraith: any experiences with JHC?
14:30 HappyEnte joined
14:32 <Aruro> what does flrc can do?
14:32 <Aruro> better than ghc
14:33 <c_wraith> when the papers were written, it had much faster results in a few benchmarks.
14:34 moop joined
14:34 <Aruro> having much faster result and still depending on TONS of software it not good.
14:34 gmhafiz joined
14:34 mjhoy joined
14:34 <Aruro> s/it/is
14:35 <Aruro> c c++ + ghc + mlcompiler. wow
14:35 <shapr> Aruro: well, it was a research compiler
14:36 kamog joined
14:36 uuplusu joined
14:36 nighty-- joined
14:36 <Aruro> fortran is still used on supercomputers
14:37 <Aruro> i was expecting fortran dependency too :)
14:38 revprez_atlanta joined
14:38 <shapr> compilers are complicated
14:38 wroathe joined
14:38 mojjo joined
14:39 <JuanDaugherty> who knew?
14:39 <Aruro> sure sure. thats why 40 years ago people already wrote good compiler :)
14:40 <Aruro> not even good readme, why people should care about this new compiler.
14:41 <c_wraith> it's really more of a meta-compiler. It's designed as a backend for many functional languages. haskell was the testbed they used to show that it could get performance improvements over real-world comilers in some cases.
14:42 NyanPasu joined
14:42 Luke joined
14:43 <Aruro> i dont think some cases actually matter in this turbulent field
14:43 indi_ joined
14:43 <Aruro> either its good and big idea, or useless
14:43 <Aruro> they abandoned this metacompiler, so result is clear
14:43 <c_wraith> that seems like a very narrow viewpoint. Worst case, it's a source of ideas for implementers of all functional languages.
14:43 <exio4> the results of their research might be helpful later on
14:43 <tsahyt> where does it say they abandoned it?
14:44 <tsahyt> also I can't think of a single good compiler from 40 years ago tbh
14:44 <tsahyt> not by modern standards
14:44 <Aruro> tsahyt: in readme
14:44 <tsahyt> 40 years ago was when C compilers were still regularly outperformed by college students with modest assembly skills
14:45 seveg joined
14:45 <Aruro> tsahyt: seems modern researches have no assembly skills :)
14:45 <tsahyt> as a modern researcher, no I don't. but I also don't need them, we have good compilers now
14:45 <tsahyt> this is going off topic though
14:46 cdg joined
14:46 <exio4> compilers are (quite often) about tradeoffs, too :)
14:47 BlueShark joined
14:47 mattyw joined
14:47 xplat joined
14:47 herzog_ernst joined
14:47 <BlueShark> probably stupid question, but what does foo.bar mean in haskell
14:47 <BlueShark> ?
14:48 <tsahyt> BlueShark: do you have some context?
14:48 <JuanDaugherty> a c compiler would still be easily outperformed by a novice assembly coder,
14:48 <c_wraith> BlueShark: all lowercase?
14:48 alx741 joined
14:48 <JuanDaugherty> you just don't often hear of it
14:48 <BlueShark> tsahyt: no, I was looking for a generic meaning. if there's one?
14:48 alx741 joined
14:48 <c_wraith> BlueShark: because there are some special syntax rules around . which depend on whether there is a space preceeding it, and whether the token preceeding it is capitalized
14:48 <BlueShark> c_wraith: yes.
14:49 rmrfroot joined
14:49 <c_wraith> BlueShark: in that case, it means . was being used as a binary operator
14:49 doomlord joined
14:49 <c_wraith> BlueShark: not really any different from foo+bar
14:49 <JuanDaugherty> and amusingly the instruction set is like fuddled now compared to the olden days like on my museum wiki page
14:49 <c_wraith> BlueShark: (except of course that . is a different operator from +)
14:50 <JuanDaugherty> ( https://en.wikipedia.org/wiki/User:Lycurgus/MoCA )
14:50 <yhhko> BlueShark: could be function composition
14:50 <Akii> isn't foo.bar just function comp..
14:50 <Akii> :D
14:50 <c_wraith> BlueShark: there is a special case with . though. When there are no spaces around it and the token before it starts with a capital letter, it's a namespace resolution operator instead. Foo.bar means "the value bar from the namespace Foo"
14:51 <yhhko> BlueShark: could be a lens-style parameter getter/setter
14:51 <yhhko> (which is also just function composition but that requires some discussion)
14:52 theelous3 joined
14:52 <Aruro> JuanDaugherty: Burroughts is very interesting company
14:54 martingale joined
14:54 mathk joined
14:54 govg joined
14:54 <Aruro> BlueShark: u see u did not give context and people wasted time to write kilometers of options
14:54 doomlord joined
14:55 <Aruro> BlueShark: hard to be clear?
14:55 vektorweg1 joined
14:55 <yhhko> Aruro: joke's on us for wasting our precious time
14:55 <mathk> @pl \x -> f x * 1 - f x
14:55 <lambdabot> liftM2 (-) f f
14:55 Rodya_ joined
14:55 <mathk> @pl \x -> f x * (1 - f x)
14:55 <lambdabot> liftM2 (*) f ((-) 1 . f)
14:56 <Akii> actually found that interesting
14:56 revprez_atlanta joined
14:56 <BlueShark> Aruro: function composition was what I was looking for. sorry about the delayed response, was busy with something.
14:56 <mathk> @pl \x -> (1 - f x) * f x
14:56 <lambdabot> ap ((*) . (-) 1 . f) f
14:56 boombanana joined
15:00 GreySunshine joined
15:01 flatmap13 joined
15:01 <JuanDaugherty> Aruro, yes they were
15:02 <JuanDaugherty> *it was/is, they bought univac
15:02 vektorweg1 joined
15:02 inr_ joined
15:02 Adeon_ joined
15:03 danza joined
15:03 a3Dman joined
15:03 twold_ joined
15:03 kipd_ joined
15:03 joeytwiddle_ joined
15:03 rellen_ joined
15:03 spinda_ joined
15:03 dh___ joined
15:03 gridaphobe_ joined
15:03 stig_ joined
15:03 yminsky_ joined
15:03 chriswk_ joined
15:03 seanparsons_ joined
15:03 eazar001 joined
15:03 lancetw_ joined
15:04 darthvorik__ joined
15:04 Heero__ joined
15:04 staffehn_ joined
15:04 w4and0er96__ joined
15:04 peteretep_ joined
15:04 isacloud_ joined
15:04 rightfold_ joined
15:04 stux|RC joined
15:04 grandy___ joined
15:04 rann_ joined
15:04 <nitrix> That's a lot of irccloud users joining...
15:04 tazjin_ joined
15:04 ess_sing joined
15:04 fizbin joined
15:04 dstockwell_ joined
15:05 ajmccluskey_ joined
15:05 tharper_ joined
15:05 jonrh joined
15:05 bjarki joined
15:05 Morgawr_ joined
15:05 vincenz_ joined
15:05 noddy joined
15:05 sjl__ joined
15:05 intelux_ joined
15:05 jaargon_ joined
15:06 ziman_ joined
15:06 barrucad1 joined
15:06 barrucad1 joined
15:06 mutsig_ joined
15:06 CindyLin1 joined
15:06 codebje_ joined
15:06 bus000_ joined
15:06 chindy_ joined
15:06 tessier_ joined
15:06 Maxdaman1us joined
15:06 ajp joined
15:06 nshepper1 joined
15:06 phz__ joined
15:06 int-e_ joined
15:06 pfoetche1 joined
15:06 Ralith_ joined
15:06 adarqui_ joined
15:06 ThugNasty joined
15:06 ThugNasty joined
15:06 seliopou_ joined
15:06 redfish65 joined
15:06 tippenei1 joined
15:06 xaimus_ joined
15:06 Solarion_ joined
15:06 tg` joined
15:06 MitchW_ joined
15:06 c0smo joined
15:06 TommyC7 joined
15:07 IndigoTiger_ joined
15:07 Randy_ joined
15:07 tjbp_ joined
15:07 nkpart_ joined
15:08 ckubrak joined
15:08 lan3y joined
15:08 fingerzam_ joined
15:08 xall joined
15:08 mbrock_ joined
15:09 kolmodin joined
15:09 zmanian____ joined
15:09 jamiis_ joined
15:09 luis` joined
15:09 brent80_plow_ joined
15:09 sns joined
15:09 lukky513_ joined
15:09 sqrt2_ joined
15:09 rootnode_ joined
15:09 bartavel` joined
15:09 mimi_vx_ joined
15:09 carc_ joined
15:09 Sornaensis_ joined
15:09 _Tristan-Speccy_ joined
15:09 baetheus_ joined
15:09 pmade_ joined
15:09 esmiurium_ joined
15:09 Saimeidae_ joined
15:09 benzrf_ joined
15:09 gregoire_ joined
15:09 Jello_Raptor_ joined
15:10 asjo` joined
15:10 orcus_ joined
15:10 xxpor_ joined
15:10 HalfEatenPie_ joined
15:11 Xnuk joined
15:11 nak_ joined
15:11 vili_ joined
15:11 xtsee joined
15:11 ctag joined
15:11 gothos joined
15:11 ReinH_ joined
15:11 djanatyn joined
15:11 <Philonous> Uh, is that normal?
15:11 Elsi joined
15:11 MasseR joined
15:12 <BlueShark> Philonous: No. It's a netsplit.
15:12 arc joined
15:12 dunx joined
15:12 timrs2998 joined
15:12 <cocreature> arguably netsplits are normal :)
15:12 marmalod1 joined
15:12 <Philonous> Oh, netplit, ok
15:12 <BlueShark> https://en.wikipedia.org/wiki/Netsplit
15:12 nbouscal joined
15:12 <BlueShark> cocreature: uhm, not *that* normal, I believe?
15:12 jbalint joined
15:12 jbalint joined
15:12 flebron joined
15:12 CARAM__ joined
15:13 Berra joined
15:13 Frankablu joined
15:13 HalfEatenPie joined
15:13 <cocreature> BlueShark: well they don’t happen every hour but they also happen often enough that you get used to it
15:13 billstclair joined
15:13 Remavas joined
15:14 incomprehensibly joined
15:14 <GreySunshine> Hello! I am trying to generate my blog with Hakyll and I'm trying to create a template by substituting values into another template. My (minimal) code is here (http://lpaste.net/354556), my template is here (http://lpaste.net/354554) and this is the error that I get (http://lpaste.net/354555). What am I doing wrong? Please help!
15:14 merijn joined
15:15 al-damiri joined
15:15 dylukes joined
15:16 mda1 joined
15:16 robkennedy joined
15:18 BlueShark left
15:19 zgrepc joined
15:20 ahf joined
15:20 jgertm joined
15:20 marfoldi joined
15:20 codesoup joined
15:21 recycletrash joined
15:21 anuxivm left
15:22 bhiliyam joined
15:22 RoyalNightGuard joined
15:22 Gurkenglas joined
15:23 cables joined
15:23 RoyalNightGuard joined
15:23 albel727 joined
15:23 jlouis joined
15:24 Remavas joined
15:24 Remavas joined
15:24 urodna joined
15:25 Remavas joined
15:26 adeohluwa joined
15:27 adeohluwa_ joined
15:28 SimpleL joined
15:28 abhiroop joined
15:28 HalfEatenPie joined
15:29 Reisen joined
15:29 sanett joined
15:30 exferenceBot joined
15:31 snowalpaca joined
15:31 Intensity joined
15:33 aglorei joined
15:33 Remavas joined
15:33 fizbin joined
15:33 LiaoTao joined
15:34 root joined
15:35 dsm joined
15:36 wizwizwizwiz joined
15:36 HalfEatenPie joined
15:37 cmsmcq joined
15:39 <wizwizwizwiz> so is there any prospect of making a haskell-like language suitable for realtime applications?
15:40 <wizwizwizwiz> i suppose that would mean some rethink of lazy eval and gc
15:40 <lyxia> linear haskell perhaps
15:40 WizJin joined
15:41 revprez_atlanta joined
15:42 oisdk joined
15:42 trism joined
15:43 <wizwizwizwiz> i'm trying to find linear haskell and i'll i'm finding is linear algebra packages,... google fail?
15:43 pmade joined
15:44 epsilonhalbe joined
15:45 JuanDaugherty left
15:45 <bodisiw> wizwizwizwiz, i think search for "linear types"
15:46 pera joined
15:46 osa1 joined
15:46 osa1 joined
15:46 <joe9> wizwizwizwiz: I am reading about jhc for a similar purpose
15:48 boombanana joined
15:48 Rodya_ joined
15:48 <wizwizwizwiz> haha i enjoyed this quote: "weights can be either 1 or omega"
15:50 sanjoyd joined
15:52 herzog_ernst joined
15:52 <dfeuer> Does modern Cabal actually work with nhc98, YHC, Hugs, HBC, Helium, JHC, LHC, or UHC?
15:53 <vaibhavsagar> wizwizwizwiz: http://blog.tweag.io/posts/2017-03-13-linear-types.html
15:54 <dcoutts> dfeuer: I'm not sure people actually test the rarer ones
15:54 <vaibhavsagar> I think at present you might enjoy pure11: https://github.com/pure11/pure11
15:54 <dfeuer> Oh, looks like nhc98 and Hugs are not actually supported....
15:55 freeside joined
15:55 <dfeuer> Looks like a bunch of cruft.
15:55 <jackhill> there are also DSLs embedded in Haskell for realtime work, like atom: https://hackage.haskell.org/package/atom
15:55 ziarkaen_ joined
15:56 ystael joined
15:56 Swizec joined
15:57 splanch joined
15:58 jmiven joined
15:58 cmsmcq joined
15:59 jmiven joined
16:00 eklavya joined
16:00 epsilonhalbe left
16:01 Dunearhp joined
16:02 JagaJaga joined
16:02 Dunearhp joined
16:02 raichoo joined
16:02 <heath> https://hackernoon.com/bayhac-2017-5ae29c196cd0
16:03 <ternary> What would be the effective difference between f x <$> y and do { result <- y; f x result }?
16:03 <ternary> They both compile, but if I use the first one, f is never actually called
16:04 <rightfold> They should give the same result
16:04 <glguy> no
16:04 <rightfold> No
16:04 <rightfold> Wait, I'm stupid
16:04 <cocreature> :t \f x y -> f x <$> y
16:04 <lambdabot> Functor f => (t -> a -> b) -> t -> f a -> f b
16:04 <cocreature> :t \f x y -> do result <- y; f x result
16:04 <lambdabot> Monad m => (t1 -> t -> m b) -> t1 -> m t -> m b
16:04 <cocreature> ternary: does that help?
16:05 indi_ joined
16:05 <rightfold> do { result <- y; f x result } should give the same result as join (f x <$> y)
16:05 <glguy> You can factor out the 'f x' as 'g' and you have: g <$> y and do { result <- y; g y }
16:05 <glguy> now you can compare g <$> y and g =<< y
16:06 Sonolin joined
16:06 <glguy> and do { result <- y; g result }*
16:07 <ternary> cocreature: Not really, I understand that <$> works on functors, but I thought that the functor instance of a monad would work like a do block
16:08 <glguy> ternary: f <$> x is like do { y <- x; return (f y) }
16:08 <glguy> ternary: It's the 'return' that you were missing if you wanted them to work the same
16:08 <ternary> Oh duh
16:08 <ternary> That makes way more sense
16:09 <ternary> Thanks
16:09 alexbiehl joined
16:12 tg joined
16:12 oisdk joined
16:16 _sras_ joined
16:16 fizbin joined
16:17 <Myrl-saki> Any thoughts on `f x x` for `f x y | x == y` ?
16:17 Rodya_ joined
16:17 _sg joined
16:18 sellout- joined
16:18 fuziontech joined
16:19 NyanPasu joined
16:20 jao joined
16:20 cpennington joined
16:21 cmsmcq joined
16:22 mattyw joined
16:22 bhiliyam joined
16:23 chriswk joined
16:23 <mbrock> ugh, ghc has now started to hang indefinitely while linking the program I'm developing...
16:24 eschnett joined
16:25 vydd joined
16:25 vydd joined
16:26 Deide joined
16:27 <geekosaur> you might look at switching the linker to gold (it's probably the bfd ld currently, which copes terribly with lots of small objects)
16:29 <cocreature> lld might also be worth considering
16:29 <nshepperd> Myrl-saki: those are called non-linear patterns. the reasons against it here seem reasonably convincing to me http://code.haskell.org/~dons/haskell-1990-2000/msg04005.html
16:29 tristanp_ joined
16:29 yaxu joined
16:29 kgadek_ joined
16:29 <mbrock> yeah, I don't know what else to try; but it's not like my program has gotten more huge, it's more that for some strange reason the link time has suddenly gone from a few seconds to ostensible infinity
16:30 <cocreature> mbrock: see https://www.reddit.com/r/haskell/comments/63y43y/liked_linking_3x_faster_with_gold_link_10x_faster/ and https://www.reddit.com/r/haskell/comments/63shj7/link_with_the_gold_linker_for_faster_build_times/
16:30 sujeet` joined
16:30 <mbrock> one time I "fixed" it by doing cabal clean and then recompiling, but that doesn't work anymore :/
16:30 <mbrock> thanks
16:30 cpape` joined
16:31 rightfold_ joined
16:31 Berra1 joined
16:31 <yaxu> If you look closely you can see the first track on this is made with Haskell https://www.youtube.com/watch?v=_OAKUlRlNF0
16:31 cables- joined
16:31 ajmccluskey_ joined
16:31 lancetw_ joined
16:31 staffehn joined
16:31 isacloud_ joined
16:31 zennist_ joined
16:31 peteretep_ joined
16:31 vin-ivar_ joined
16:31 Wamanuz joined
16:31 saidinwot1 joined
16:31 obadz- joined
16:32 <geekosaur> bfd ld hits a knee abruptly and starts swapping, iirc. so you may well be right on the edge of what it can cope with
16:32 jstimpfl1 joined
16:32 angseus_ joined
16:32 <geekosaur> ...wheeeee
16:32 nycs joined
16:32 defanor joined
16:32 <cocreature> yaxu: nice :)
16:32 tinkyholloway joined
16:32 m1dnight_ joined
16:32 fakenerd joined
16:32 zero_byte joined
16:32 ajp joined
16:32 _guios joined
16:32 bydo joined
16:32 moop joined
16:32 SuprDewd joined
16:32 tgeeky joined
16:32 katychuang_ joined
16:32 tero- joined
16:32 Nicmavr joined
16:32 ccomb joined
16:32 cdidd joined
16:32 CuriousErnestBro joined
16:33 alphor joined
16:33 jokester joined
16:33 Randy joined
16:33 jrslepak joined
16:33 MindlessDrone joined
16:33 lopex joined
16:33 darthvorik_ joined
16:33 tjbp joined
16:33 gmhafiz joined
16:33 leah2 joined
16:34 Geekingfrog joined
16:34 <Myrl-saki> nshepperd: Aww. :C
16:34 Wingsorc joined
16:35 rellen joined
16:35 abhiroop joined
16:35 electrostat joined
16:35 yminsky joined
16:35 joeyh joined
16:36 t7 joined
16:36 ternary joined
16:36 epsilonhalbe joined
16:37 bennofs joined
16:37 <scav> Been learning Haskell for a couple of weeks now, and it just dawned on me how beautiful the language is
16:37 lithie joined
16:37 Amadiro joined
16:37 <scav> Never had an emotional reaction to a language before. Is this normal? :)
16:38 mmn80 joined
16:38 <freeside> haskell improved my dreams. i'm flying a lot more now, and changing the environment too.
16:39 <joe9> scav: it puts you through the grinder.
16:39 kipd joined
16:39 <sm> highs and lows :)
16:39 <nshepperd> the grinder of love
16:39 grumble joined
16:39 wroathe joined
16:39 <scav> hehe
16:39 twold joined
16:39 tharper joined
16:40 flohsor joined
16:41 ragepandemic joined
16:41 <_sras_> Is there a way to rebuild a stack project even if none of the files have changed?
16:41 tathougies joined
16:42 <adamCS> _sras_: "stack clean <name of local project>"
16:42 yaxu left
16:42 vlatkoB joined
16:42 <adamCS> "stack clean" will clean (and rebuild) that and all the "packages" as well.
16:43 <adamCS> or you could delete ".stack-work" and then it will rebuild/redownload all the dependencies as well. I think.
16:43 <adamCS> start with stack clean --help
16:44 solarus joined
16:45 <sm> or stack build --force-dirty
16:45 <Sornaensis_> TIL intel was working on a back end for haskell written in SML
16:46 cmsmcq joined
16:47 ggherdov joined
16:47 <scav> Sornaensis Haskell Weekly? :)
16:47 `^_^v joined
16:47 mwilly joined
16:48 <mbrock> gold doesn't seem to help; moreover, while waiting, there is not even a gold process running, and in fact no process is taking much CPU or memory at all, so something strange is going on
16:49 raichoo joined
16:51 <Sornaensis> scav: it was on hn
16:51 <scav> Oh - generally avoid that site
16:54 eazar001 joined
16:55 path[l] joined
16:57 fresheyeball joined
16:57 <fresheyeball> anyone know if there is a way to make ghc-mod work with a custom dist folder?
16:57 fizbin1 joined
16:57 `^_^v joined
16:58 <fresheyeball> I like cabal configure --builddir foo
16:58 fizbin joined
17:00 fizbin2 joined
17:00 mbeidler joined
17:00 lukexi joined
17:00 <Sornaensis> scav: ?
17:00 runeks joined
17:00 sa1_ joined
17:01 bitonic joined
17:01 edwardk joined
17:02 amatecha joined
17:02 <mbrock> haha, sorry for the FUD, I'm just an idiot and was running a blocking command after make in a shell pipeline :(
17:02 <mbrock> but thanks for the gold tip ;)
17:05 RoyalNightGuard joined
17:05 mstruebing joined
17:06 Luke joined
17:07 ziocroc joined
17:07 danthemyth joined
17:09 noexcept joined
17:09 cmsmcq joined
17:11 mada joined
17:12 recyclet_ joined
17:13 abhiroop joined
17:14 ragepandemic joined
17:14 iAmerikan joined
17:14 bjz joined
17:14 Swizec joined
17:15 ragepanda joined
17:15 path[l] joined
17:16 oleksiyp joined
17:19 zeroed joined
17:19 zeroed joined
17:20 dedgrant joined
17:21 seanparsons joined
17:23 <tsahyt> is there a way to get GHC to show the context of a typed hole? e.g. Ord t, etc
17:23 sepp2k joined
17:23 LiaoTao joined
17:23 HappyEnte joined
17:23 bhiliyam joined
17:23 <tsahyt> I'm getting additional context out of a pattern match on a GADT, but it's pretty much invisible. it's there because I can make it type check but during development it'd be nice to see it
17:25 HappyEnte joined
17:26 `^_^v joined
17:26 peterbec` joined
17:26 carter joined
17:27 <nshepperd> hm, maybe you could manufacture one of those 'could not deduce <constraint>' errors
17:27 richi235 joined
17:27 unK_ joined
17:27 seveg joined
17:29 lykos_ joined
17:30 <lykos_> I'm trying to make some code be multithreaded, when it's currently being processed in a single thread:
17:30 tput joined
17:31 <lykos_> moveEvals = [(m, evaluateMove m) | m <- candidateMoves]
17:31 <nshepperd> tsahyt: class Hole a where { __ :: a }
17:31 <nshepperd> tsahyt: use __ as a hole that also prints context :)
17:31 <lykos_> where I then select (effectively) the max element from the list.
17:32 <tsahyt> that's a creative solution
17:32 <lykos_> Does anyone here know of a good way to do that?
17:32 <lykos_> (pardon the interleaved messages)
17:32 <nshepperd> actually printing the context for normal holes maybe needs to be added
17:34 <Sornaensis> {-# LANGUAGE InformativeHoles #-}
17:34 <Sornaensis> or maybe SmartHoles
17:34 gcross_ joined
17:35 RoyalNightGuard_ joined
17:37 Nicmavr joined
17:37 <nshepperd> -XDeepHoles
17:37 path[l] joined
17:38 replay joined
17:38 Skami joined
17:43 HappyEnte joined
17:43 yellowj joined
17:44 tabaqui joined
17:44 xall joined
17:44 path[l] joined
17:45 flohsor joined
17:46 pbogdan joined
17:47 path[l] joined
17:47 fizruk joined
17:47 Morgawr joined
17:50 mekeor joined
17:52 seveg joined
17:52 mtesseract joined
17:52 AndreasK joined
17:53 oleksiyp joined
17:54 ragepanda joined
17:59 replay joined
17:59 simendsjo joined
18:00 twanvl joined
18:00 epsilonhalbe joined
18:01 sleffy joined
18:02 BlueRavenGT joined
18:03 ragepanda joined
18:04 <joe9> is there a writeFile that uses RawFilePath instead of FilePath?
18:04 PatrickRobotham joined
18:04 cyborg-one joined
18:04 flatmap13 joined
18:06 ystael joined
18:07 Ch3ck joined
18:07 path[l] joined
18:08 <pavonia> joe9: You mean with system-dependent encoding?
18:08 cyborg-one joined
18:09 <joe9> pavonia: no
18:09 <pavonia> rawfilepath has writeFile :: RawFilePath -> ByteString -> IO ()
18:10 <geekosaur> they want a version of writeFile that uses POSIX pathname semantics instead of the String one
18:10 <joe9> pavonia: I wanted to check if I am missing something simple as my filename is Text and I did not want to unpack the file name before writing to it.
18:10 <dxtr> I postgresql-simple the recommended postgresql library?
18:10 <dxtr> Is*
18:10 thatguy joined
18:10 <geekosaur> note that this is the *pathname* not the *content*
18:10 <dxtr> I find the documentation to be.. Lacking :)
18:10 <joe9> let me check rawfilepath. Thanks.
18:10 CoderPuppy joined
18:11 revprez_atlanta joined
18:11 <joe9> pavonia: exactly what I wanted. Thanks.
18:11 <pavonia> No problem
18:12 rinon joined
18:12 ertesx joined
18:13 Cassiopaya joined
18:13 <joe9> pavonia: is there something like that which uses a Text filename and Text arguments too?
18:13 <geekosaur> afaik there is nothing that uses Text for filenames
18:14 <geekosaur> it's even less safe than the default String
18:14 <joe9> geekosaur: oh, ok. good to know. Thanks.
18:14 <geekosaur> yes, I know everyone desperately wants all unixes to redesign themselves around unicode paths
18:14 <geekosaur> it won't
18:15 <geekosaur> pathnames are ByteString and you cannot safely infer any encoding for them
18:15 iomonad joined
18:16 hamishmack joined
18:17 hackagebot joined
18:17 infu joined
18:17 <joe9> geekosaur: ok, Thanks.do you have any opinion on JHC btw? I am looking for a small haskell that I can port to a different platform and that seems to be the best out there.
18:17 <geekosaur> jhc's effectively dead :(
18:18 mtesseract joined
18:18 <joe9> i understand but that is the only one I could find. the core seems to stick with Haskell 2010 and that is good enough for my purposes.
18:19 atomi joined
18:19 <geekosaur> for portability it should be pretty good. one shortcoming and I think the reason it's dead now is that there've been ongoing issues with garbage collection
18:20 <joe9> pavonia: as an fyi, this seems similar too.
18:20 <joe9> https://hackage.haskell.org/package/posix-paths-
18:20 <joe9> pavonia: but it does not have writeFlie
18:20 <joe9> just for joining the dirs and filenames
18:21 <joe9> geekosaur: oh, really. good to know. That is the kind of info that I want before I end up with a dead end. Thanks a lot.
18:21 <Tuplanolla> Path names are less than 64 alphanumerical, plus, dash, dot, at or underscore characters or you will be given a stern look.
18:21 raichoo joined
18:21 sigmundv_ joined
18:22 Glooomy joined
18:22 <pavonia> joe9: Apparently, it's supposed to be an extension to the unix package
18:22 <geekosaur> actually my recollection (you probanly want to dig up the mailing list and look for details) is the original didn't really do gc, then a boehm gc was implemented, then I think some preliminary work was done on a true gc and things stalled?
18:23 uglyfigurine joined
18:23 <geekosaur> and the boehm gc was itself not fully implemented and I think a bit buggy
18:24 bhiliyam joined
18:24 ragepanda joined
18:25 path[l] joined
18:25 <Tuplanolla> What should I call things that aren't quite large enough to be packages? Modulets? Projectoids?
18:26 <glguy> Packets
18:26 <Cale> Letters
18:26 <Cale> lol
18:26 <joe9> geekosaur: good info. Thanks a lot. are you aware of something similar that is more active?
18:26 <geekosaur> isn;t that what French does :)
18:27 fizruk joined
18:27 <joe9> uhc?
18:27 <geekosaur> no, afaik the only active haskell project is ghc, although utrecht students still hack on uhc (it's on github these days)
18:27 darkSeid_ joined
18:27 <Tuplanolla> A hypothetical package, packet, pack, p hierarchy?
18:27 zeroed joined
18:27 M-kevinliao joined
18:27 <geekosaur> but afaik only utrecht folks care about it any more
18:27 <Cale> parcel
18:27 <rightfold> Is anyone aware of a purescript-halogen port to Haskell?
18:28 wildlander joined
18:28 ner0x652 joined
18:28 <joe9> I read that JHC source is easy to comprehend. that is what attracted me to it.
18:28 jonrh joined
18:28 <rightfold> For GHCJS or something like GTK+
18:29 <geekosaur> yes, and I think one of the problems was that it would have to be redesigned completely to take proper advantage of even Boehm gc much less a true gc
18:29 <Cale> rightfold: Perhaps you're looking for reflex-dom?
18:29 <geekosaur> (re jhc)
18:29 <Cale> rightfold: https://github.com/reflex-frp/reflex-platform/blob/develop/README.md
18:30 <joe9> oh, wow. did not realize the effort involved. Thanks geekosaur.
18:31 seveg joined
18:31 sm joined
18:31 <rightfold> Cale: that doesn't seem like the same model
18:32 ystael joined
18:32 indi_ joined
18:33 <rightfold> Seems more like an FRP approach
18:33 <Cale> Well, it is
18:33 ragepanda joined
18:33 <Cale> I'm not sure what you meant by "port", and I don't actually know what halogen is about :)
18:34 <Cale> (beyond quickly looking it up)
18:34 epsilonhalbe left
18:35 <rightfold> Halogen is basically Elm's model except state is local and doesn't have to be propagated all the way from the top
18:35 monadicDuck joined
18:36 zeroed joined
18:36 zeroed joined
18:36 <Cale> (The first thing I found about Halogen makes it look like it's trying to do FRP to some extent, though it looks similar to Elm's we-can't-decide-if-this-is-a-behaviour-or-event-Signal-thing)
18:37 <math493> f [] = []
18:37 <math493> f (x:xs) = f ys ++ [x] ++ f zs where {ys = [a | a <- xs, a <= x]; zs = [b | b <- xs, b > x]}
18:37 <math493> What does this do? :)
18:37 <Cale> it sorts a list
18:37 fragamus joined
18:37 <math493> Oh. So I should be able to call it like... f [1..10]?
18:37 <Cale> yeah, though that would be a boring example
18:38 <math493> *** Exception: <interactive>:144:1-92: Non-exhaustive patterns in function f
18:38 <rightfold> math493: What is the type?
18:38 <math493> Apparently it doesn't even work
18:38 <Cale> math493: Where did you put it?
18:38 <math493> rightfold: The type of what?
18:38 <rightfold> f
18:38 <Cale> math493: Note that if you type those lines into ghci, the second line will shadow the first
18:38 <math493> Cale: In GHCi
18:38 <math493> Cale: Oh...
18:38 <Cale> and you'll end up with an incomplete definition
18:38 <math493> That's why.
18:38 <math493> Semicolon?
18:38 <Cale> You should put the definition in a file and load it
18:38 <Cale> or yeah, semicolon
18:38 <Cale> Or :{
18:38 <Cale> and then the definition
18:39 <Cale> and then :}
18:39 <lyxia> sad then happy
18:39 <math493> Yeah, it actually sorts the sequence :)
18:39 <Cale> But really, you shouldn't define things at the ghci prompt for the most part :)
18:39 <math493> Cale: I'll try to avoid it :)
18:39 <kadoban> math493: It looks to be an implementation of quicksort, if that helps
18:40 <math493> Why does it sort? I came across it in some slides.
18:40 <Cale> okay, let's look closely at these lists ys and zs
18:40 wroathe joined
18:40 <Cale> ys is the list of elements a where a is selected from xs, and a is less than or equal to x
18:40 <math493> http://imgur.com/a/r4TyC - the slide, if you want to see it. From a MOOC
18:40 <Cale> that's how "ys = [a | a <- xs, a <= x]" is read
18:40 <math493> An archived MOOC though.
18:41 <math493> I'm just browsing through the material.
18:41 <Cale> and then zs is similarly the list of elements b from xs where b is greater than x
18:41 <Cale> So we know that in an eventually sorted result, x will have to occur between the elements in ys and the elements in zs
18:41 <math493> Cale: It seems clever, even though it might be boring for experienced Haskell programmers. I mean, it's very... concise.
18:41 <Cale> It's quicksort
18:42 nbro joined
18:42 <math493> Nice. Quick sort in a one-liner? Wow.
18:42 <Cale> (well, depending on what you consider quicksort to be -- it's not in-place)
18:42 <mauke> math493: what other programming languages do you know (if any)?
18:42 bollu joined
18:43 <math493> mauke: Well, some Java and Python (if Python counts as a programming language, that is). And then MATLAB and R, but they probably not count either.
18:43 <Cale> math493: So, yeah, we sort both ys and zs, recursively, and then stick x in between the results
18:43 mikecaruso joined
18:43 ragepanda joined
18:43 jeltsch joined
18:43 <math493> I like that example, especially after the explanation.
18:43 <mauke> I don't remember how python does list concat
18:43 <joe9> geekosaur: if you were to guess, how much effort do you think would jhc require? atleast a few months of dedication ?
18:44 <Cale> math493: I don't think I ever fully understood quicksort until I saw an example much like that one
18:44 <math493> I guess Haskell does not have a built-in sort function?
18:44 <Cale> It does.
18:44 <Cale> There's a sort in Data.List
18:44 <geekosaur> how do you define built-in?
18:44 <Cale> which is a merge sort
18:44 <kosmikus> depends on what you mean by "built-in"
18:44 <geekosaur> the whole language is not in the Prelude
18:44 <Cale> Well, yeah, it's not really *built in*
18:44 <math493> Yeah, OK :)
18:44 <Cale> It's just part of the standard library
18:44 <geekosaur> and very little is wired into the compiler
18:45 <Cale> The sort in Data.List is a merge sort
18:45 <Cale> (which works better for linked lists than quicksort, and has a better worst case complexity)
18:45 <mauke> ys = [a for a in xs if a <= x]; zs = [b for b in xs if b > x]; return f(ys) + [x] + f(zs)
18:45 <mauke> I believe that's valid python code
18:45 <math493> mauke: Let me try :D
18:46 <geekosaur> joe9: I don't really know. I think rewiring jhc to properly support gc instead of manually managed memory allocation would be fairly significant effort (year+) but that's likely the way it should ultimately go.
18:46 pera joined
18:46 <geekosaur> also it's unlikely to support all of ghc's extensions, and some of the harder ones to implement are very widely used (mtl relies on multiparameter typeclasses, for example)
18:46 Itkovian joined
18:47 <joe9> geekosaur: Thanks again.
18:47 <math493> mauke: What's the input list in your example?
18:47 <geekosaur> (well, MPTC *itself* is easy, but making them usable requires functional dependencies or type families)
18:47 <math493> xs?
18:47 <math493> I guess?
18:47 <mauke> math493: [x] + xs
18:47 <Cale> Yeah, you'd need to take apart the list which was input
18:48 <mauke> same as in the haskell version. but for a complete translation you'd have to check for an empty list and otherwise shift the first element off
18:48 <math493> mauke: So it's not *that* clean in Python :D
18:48 <mauke> indeed
18:48 <Cale> right
18:48 fnurglewitz joined
18:48 <* mauke> proceeds to write a perl version. heh
18:49 <Cale> Pattern matching is so nice to have, it's really pretty sad that more languages don't have it.
18:49 <math493> mauke: But you didn't really define f, did you?
18:49 <mauke> this is part of the definition of f
18:49 <fnurglewitz> Cale, heh, some languages don't even have type aliases
18:49 cpennington joined
18:49 chlong joined
18:49 <math493> mauke: I mean, in your Python code.
18:49 <ertes> just today i gave guile scheme another shot as a shell replacement on systems where i'd rather not install nix+GHC
18:50 <fnurglewitz> (i'm not pointing my finger on you, Java)
18:50 <Cale> fnurglewitz: Type aliases I can live without, but algebraic types, pls
18:50 <joe9> geekosaur: on a slightly different note, would you recommend any other language or tool that can be lazy, pure and pattern matches? Something that can be easily ported?
18:50 <ertes> perhaps the most important module for me was (ice-9 match), which provides pattern matching
18:50 <ertes> programming without pattern-matching has become a really horrible experience for me
18:50 <Philonous> How well do algebraic types work without a static type system though?
18:50 <mauke> math493: yes, that's what I meant
18:51 <Cale> Philonous: Well, Erlang sort of has that...
18:51 <Cale> iirc
18:51 <ertes> Philonous: not very great, because the compiler is no longer your friend
18:51 <Philonous> Oh? Interesting, should look into that
18:51 <mauke> sub f { my ($x, @xs) = @_ or return; f(grep $_ <= $x, @xs), $x, f(grep $_ > $x, @xs) }
18:51 <geekosaur> joe9, I don't know of one. But it occurs to me that, depending on what you are looking for, you could also see about resuscitating Hugs (note that it's just an interpreter though)
18:51 <mauke> that's actually not bad at all
18:51 fragamus joined
18:51 reliability joined
18:51 <math493> mauke: That looks like Chinese to me :D
18:51 <ertes> Philonous: for example the only way to really model your application is in terms of prose or some form of pseudo-syntax
18:51 <Cale> Not sure if it's full algebraic data types, but it has some amount of pattern matching, which extends to picking apart cons lists, and tuples
18:52 <geekosaur> joe9, or, piggybacking on the other discussion going on here, any language can be made lazy by turning terms into functions, so you could think about Erlang if you're willing to compromise on purity
18:52 <reliability> Hi. I have a typeclass YesNo, can someone tell me what is wrong with this: instance (Integral a) => (YesNo a) where
18:52 <Cale> Philonous: and I believe it also has atoms which can be pattern matched against
18:53 <Cale> Philonous: So at the very least, you can build tuples whose first component is an atom that you match as if it were a data constructor
18:53 <ertes> reliability: need more information
18:53 <rightfold> Erlang pattern matching is pretty cool
18:53 <geekosaur> (or hugs could be turned into an erlang-style language with a fair amount of work. in fact I could see someone retargeting it to beam instead of its own bytecode, and suddenly you get a larger universe to play with)
18:53 <ski> pattern-matching in Erlang is basically the same as in Prolog (except it's *matching*, not *unification* as in Prolog. and you don't have compound terms labelled with "functors", you have tuples. still have atoms/symbols, though)
18:53 <rightfold> It can do stuff like dissecting bytestrings and match on equality of two parts etc
18:53 revprez_atlanta joined
18:53 <ski> also, you can match on a previously instantiated variable in Erlang
18:53 <reliability> ertes: https://pastebin.com/UqZZSHGJ
18:54 <joe9> Curry seems to be the king of pattern matching though , imho.
18:54 <ertes> reliability: the problem with your instance is that it's an instance for *all* types
18:54 <ski> it's also interesting that if you instantiate a variable in all branches of a `case' (or `if' or `receive'), then you can use that variable afterwards
18:54 <geekosaur> reliability, the context plays no part in instance selection
18:54 <ertes> reliability: instance resolution is a bit counter-intuitive in that regard… the context of the instance (the (Integral a) part) doesn't matter for instance resolution… it is only used to constrain usage *after* resolution
18:54 <ski> can't match on lambdas, though
18:55 <geekosaur> the second instance is "instance YesNo a where" plus a use-site check to see if the selected a has an Integral instance
18:55 <monochrom> Philonous: Various Scheme compilers and libraries provide ADT mechanisms.
18:55 <ski> there's a typed scheme in Racket, iirc
18:55 <reliability> ok, what do you mean by instance resolution?
18:55 dhil joined
18:56 eddyda joined
18:56 <ertes> reliability: the compiler selects an instance based on types… this selection process is called instance resolution
18:56 <ertes> > "abc" <> "def"
18:56 <lambdabot> "abcdef"
18:56 <ertes> because the arguments are lists, the list instance of Monoid is used
18:57 <reliability> ok
18:57 <ertes> reliability: in general don't write a mere variable after the class in an instance… this is almost never the correct way to do it
18:57 <reliability> But, given the fact that, e.g., 1 is a an integral, couldn't the compiler figure out which function to use?
18:58 <monochrom> Instance selection follows the motto of "better sorry than safe".
18:58 meoblast001 joined
18:58 <ertes> reliability: the problem with your instance is that it conflicts with your (YesNo [a]) instance
18:59 <math493> Does functional programming languages like Haskell have loops or do you always use things like map here?
18:59 <reliability> But lists are not integral, are they?
18:59 zeroed joined
18:59 <ertes> reliability: yesno [5] -- instance resolution will come up with *both* instances in this case
18:59 oleksiyp joined
18:59 <ertes> reliability: that's correct, and that's where the fact that instance resolution does not care about context comes in
19:00 <geekosaur> reliability, you're still missing that the context (Integral a) doesn't matter for instance selection
19:00 <ertes> it will still select both instances and then complain about overlapping
19:00 <reliability> ok, i see
19:00 <monochrom> math493: I always write my own recursion and I always use things like map.
19:00 bollu joined
19:00 <rightfold> math493: A loop is a construct that executes the same code many times in a row
19:00 robertkennedy joined
19:00 <reliability> but how do I achieve what I wanted to achieve? ;-)
19:00 <math493> rightfold: Yes, I know :)
19:00 zeroed_ joined
19:01 <rightfold> math493: In Haskell you do this with recursion, or with abstractions that hide the recursion from you (such as map, traverse, cata, foldl, etc)
19:01 <Cale> math493: There are loops, but they are generally higher order functions :)
19:01 <math493> What I asked is: Does it exist in Haskell?
19:01 <Cale> :t forM
19:01 <lambdabot> (Monad m, Traversable t) => t a -> (a -> m b) -> m (t b)
19:01 <Philonous> math493, You can implement while/for loops if you really want to, but I've never actually needed them
19:01 <math493> I was just curious.
19:01 <Philonous> math493, It's not part of the language, but you can implement it yourself
19:01 RoyalNightGuard joined
19:01 <Cale> oh, of course, this is now right off the deep end :D
19:01 <monochrom> Recursion exists in Haskell. Loop exists in Haskell iff loop means recursion.
19:01 Mazkiller joined
19:01 <monochrom> To me, loop means recursion, same difference, so yes.
19:02 <math493> monochrom: But you can only do things recursively, not iteratively? :)
19:02 <monochrom> What's the difference?
19:02 <math493> monochrom: Well, the result is the same, but... different approaches :)
19:02 <rightfold> Such abstractions should be preferred over manual recursion, as they make it more difficult to introduce nonterminating loops
19:02 <Cale> anyway, this is a little bit general, but it takes some data structure whose elements can be traversed, and a function which, given an element of that structure, will determine which action to take, to produce some result, and will give you an action which iterates over all the elements and constructs a new data structure of the same shape as the original with the results replacing the elements
19:02 zeroed joined
19:02 <monochrom> Some recursions I write are conceptually while-loops.
19:03 <math493> Cale: What are higher order functions? Sounds fishy :D
19:03 <Cale> math493: Functions which take other functions as arguments
19:03 <ertes> reliability: newtype NumYesNo a = NumYesNo { fromNumYesNo :: a }
19:03 <Cale> (e.g. the loop body)
19:03 <monochrom> For example foldl's code is a loop. (OK, I didn't write it.)
19:03 <ertes> reliability: instance (Integral a) => YesNo (NumYesNo a)
19:03 <math493> Cale: Hm, so how would I use a keyword like "for"? Not that I need to, but I was just wondering
19:03 <monochrom> Or rather, s/is/is conceptually/
19:03 <Cale> math493: I can write an accurate representation of C's for loop as a function in Haskell, but nobody would use it :)
19:04 <monochrom> There is no keyword "for". You just write recursion, or use a library function that does the recursion for you.
19:04 <math493> But I guess if-else-constructions exist in Haskell, right?
19:04 <Cale> math493: We'd write its definition recursively, of course :)
19:04 <Cale> Yeah
19:05 <Cale> (and if they didn't, well, pattern matching)
19:05 eschnett joined
19:05 Itkovian_ joined
19:05 <monochrom> if-then-else is orthogonal to "for".
19:05 <math493> Cale: Can pattern matching always replace if-else-things?
19:05 <Cale> Yeah, it's just pattern matching against Bool
19:05 <ertes> math493: you may wonder how exception handling works in haskell… 1. we have first-class actions, so actions (effectful programs) are regular values, 2. we can write functions that take actions and return actions
19:05 <math493> Or could there be cases where it's really needed?
19:05 <ertes> :t finally
19:06 <lambdabot> IO a -> IO b -> IO a
19:06 <ertes> now something like 'finally', which would be a built-in construct in another language, is just a regular function
19:06 takle joined
19:06 <Cale> You can always replace if foo then bar else quux with case foo of True -> bar; False -> quux
19:06 <math493> ertes: Cool :)
19:06 <rightfold> There is if/else, however constructs like "if null xs then 0 else head xs" should be avoided as they make it difficult to move the code around due to flow-encoded assumptions
19:06 <ertes> math493: with this power in hand, we tend to write more domain-specific control constructs than something like a "for loop"
19:07 <math493> rightfold: But code like Cale showed me is OK?
19:07 <ertes> there is no benefit in having for-loops
19:07 magneticduck joined
19:07 <math493> rightfold: Like case foo of True -> bar; False -> quux
19:07 takle joined
19:07 <math493> Or is this equally bad?
19:07 <monochrom> Untill and unless you consider [1..10] to be a for-loop.
19:07 <rightfold> math493: well you'd prefer case xs of { [] -> 0; (x : _) -> x }
19:08 <rightfold> So that moving the code around will break if you accidentally try to take the head without knowing the list is nonempty
19:08 <rightfold> It won't compile because x won't be in scope
19:08 <ertes> math493: the next ingredient is laziness: we can use data structures to model control at no cost
19:08 Avogadro joined
19:08 <ertes> math493: mapM_ print [0..] -- this program prints all natural numbers, if you wait long enough… it runs in constant memory
19:09 <math493> ertes: Haha, maybe there will be no more memory, if I wait long enough? :D
19:09 <ertes> math493: ok, that was a lie… the numbers grow, of course =)
19:09 <Cale> Well, if you wait long enough it will eventually use all the memory on the gigantic integers
19:10 marr joined
19:10 <Cale> (but practically, no)
19:10 <math493> :D
19:10 <ertes> but the list is pretty much non-existent… it compiles into the tight loop you would have written by hand using a for-loop
19:10 <reliability> ertes: slowly but surely, it starts to make sense... ;-)
19:10 <reliability> ertes: thanks
19:11 <math493> What are some cool features of Haskell? Something which Haskell is particularly good at, which would be ugly or maybe even impossible in other languages?
19:11 <monochrom> Programming proves the Sapir-Whorf effect. Programmers' mind are imprisoned by their language.
19:11 <math493> Other languages = non-functional languages, that is
19:11 <ertes> math493: the type system
19:11 <math493> ertes: How is the type system special?
19:11 fizbin joined
19:12 <math493> ertes: Is it different?
19:12 <Cale> math493: That's a big question... we can bite off pieces of it :)
19:12 <math493> :D
19:13 <Cale> So, starting on the shallow end, first off all we have type variables (parametric polymorphism) which is convenient to use and people use it everywhere
19:13 <Cale> :t map
19:13 <lambdabot> (a -> b) -> [a] -> [b]
19:13 <Athas> math493: type-system wise, higher-kinded types are unusual for Haskell.
19:13 <math493> I was just wondering *why* Haskell was great. I only started learning Haskell today and I went though some tutorials and examples. And from what I understand, many people really like it for its... conciseness.
19:13 <ertes> math493: it's expressive (if your program is correct, it can most likely be expressed in haskell), it's self-dependent (rarely needs your help in the form of type signatures), it's supportive (because the compiler has so much information about your program, it can write parts of your code), etc.
19:13 <monochrom> Parametric polymorphism make a difference. Suppose I provide you a function "f :: a -> a" and I keep my code secret. Still, in one test you will know what it does.
19:14 <Athas> math493: are you wondering why Haskell is good compared to mainstream languages, or compared to other functional languages?
19:14 <math493> Athas: Compared to mainstream languages like Python and Java :)
19:14 <Cale> math493: Actually, far more than the conciseness, I like the fact that when programs compile, with an almost unreasonably high probability, they also work
19:14 <monochrom> If you test with "f ()" and its answer is "()" then you know my f is as good as \x -> x.
19:14 <math493> I never programmed functionally before.
19:14 <ertes> math493: also it's a sane language… types in haskell are for programmers, not for the compiler
19:15 <rightfold> math493: I use a language closely related to Haskell for my job, and when people say "if it compiles, it works", they barely lie. This is the main reason I like it so much
19:15 <Athas> math493: I find it very useful that you can trust the types. When you program purely, there are no hidden effects. A function that claims to take an integer and return a bool (or whatever) really *will do nothing else*.
19:15 <ertes> compare: const :: a -> b -> a
19:15 <Cale> math493: I work as a web developer for Obsidian Systems, we build web applications pretty much entirely in Haskell -- with the frontend compiled to Javascript for the web by GHCJS or ARM code for mobile devices by GHC, and the backend compiled to x64 code by GHC.
19:15 <Cale> math493: This means we get to share code and types between our frontend and backend
19:15 <ertes> to: tempalte <typename A, typename B> A const_(A x, B y);
19:15 <ertes> *template
19:15 <monochrom> In fact, here is my secret code: f = fmap fix pure
19:16 <math493> Cale: Oh, it can also be used for web applications?
19:16 <Cale> I can start a refactor on the backend, or in the code shared between the two, and the type errors propagate through the backend and frontend, letting me know all the things which need updating
19:16 arw joined
19:16 <Cale> math493: Sure. It can be used for pretty much anything.
19:16 <math493> Cale: I know PHP, but I really dislike it after I started learning other languages. It was my first language.
19:16 <monochrom> You haven't known fmap, fix, or pure, so you "don't know" what my f does. No matter. The type is a->a, so you just need one test:
19:16 <monochrom> > fmap fix pure ()
19:16 <lambdabot> ()
19:16 <monochrom> Therefore fmap fix pure = id.
19:16 <monochrom> You don't even need other tests.
19:17 <Cale> math493: The one area where you kind of can't use it directly is on microarchitectures, but people still use Haskell to emit the programs to run on their microcontrollers :)
19:17 hybrid joined
19:17 <rightfold> If the type is a -> a you don't even need a test
19:17 jsgrant_ joined
19:17 <ertes> @djinn a -> b -> a
19:17 <lambdabot> f a _ = a
19:17 <math493> Athas: That's a nice thing :)
19:17 <monochrom> I need a test. I don't know whether it comes out bottom.
19:17 <Cale> (i.e. one-shot compiler sort of stuff)
19:17 <rightfold> monochrom: meh bottom
19:18 <Athas> math493: it may sound like a small thing, but it means you need to keep fewer moving parts in your head when thinking about a piece of code.
19:18 fizruk joined
19:18 <monochrom> And a->a is not a very real-world example.
19:18 <Athas> Because interfaces are simpler and more explicit.
19:18 <dolio> monochrom: You need two tests.
19:18 <monochrom> A more realistic example is a->[a]. This is something you may actually use.
19:18 <Cale> math493: About a month ago, a coworker and I took a web application that our team had been working on for a year for a client, and reworked the entire thing to be multi-tenant -- so you'd have a single backend serving multiple copies of the application each with their own separate, and secure database.
19:18 <dolio> monochrom: In Haskell, at least.
19:18 <monochrom> And it needs a test even if you are assured of no bottom.
19:19 <dolio> Wait, what am I saying. That's wrong.
19:19 Deide joined
19:19 <Cale> math493: It took us 2-3 days to do what would be a few weeks to a month or more if we didn't have the type system
19:19 <rightfold> monochrom: you need to test the output length, that's all :)
19:19 <math493> Cale: That sounds like much work :)
19:19 flatmap13 joined
19:19 <monochrom> But if you test it and it says "f () = [(), (), ()]", then you know f is as good as \x -> [x,x,x]
19:19 nagyf joined
19:19 <monochrom> Yeah.
19:19 cpup joined
19:19 <dolio> Now in that example, you need more tests.
19:19 <ertes> math493: not in haskell… easy refactoring is one of the secret weapons of a haskell developer =)
19:19 <rightfold> All elements are the same, and the length is independent of the input 👍🏻
19:20 chreekat joined
19:20 <Athas> ertes: er, except that Haskell has no refactoring tools.
19:20 ericsagnes joined
19:20 <Athas> It's much easier to refactor in Java or C#, but it's harder to say whether the refactoring is correct.
19:20 zar joined
19:20 <Athas> (Or maybe not even that, in most cases.)
19:21 <ertes> Athas: practical refactoring does not involve renaming functions
19:21 <monochrom> OK, right, my test does not distinguish \x -> [x,x,x] from \x -> x `seq` [x,x,x]
19:21 <Cale> math493: Basically, we changed a couple of basic types: the type representing a pool of connections to the database, and the type representing a user token being the main ones -- and the compiler pointed us at everything that needed to change throughout the entire system
19:21 <ertes> Athas: it involves more abstraction, more functionality
19:21 <monochrom> This one may actually benefit from testing "f undefined"
19:21 <ertes> so tools are useless… the only useful tool is the compiler
19:21 <Athas> ertes: things like 'extract to method'-functionality?
19:21 <monadicDuck> %s/varName/newVarName/g
19:21 biglambda joined
19:21 <monadicDuck> #refactor
19:21 <math493> Cale: That sounds really nice.
19:21 <ertes> Athas: never needed that, honestly
19:21 <rightfold> Types and referential transparency are more useful refactoring tools
19:21 mattyw joined
19:22 <math493> Even though the concept is a bit hard to grasp, I think it might be worth learning :)
19:22 <Athas> Definitely! Haskell is the best general-purpose programming language there is.
19:22 <rightfold> They ensure that moving code around and deduplicating it is safe
19:22 <rightfold> No further knowledge about the code is required
19:23 <ertes> Athas: i can see how a java developer might need it, but in haskell? that's why we love our associativity =)
19:23 fizruk joined
19:23 <math493> Do you know any good "toy examples" which show some of the strengths of functional programming, which are readable for beginners?
19:23 <Cale> math493: So, one of the components of the type system is algebraic data types, these are types which have multiple constructors, each of which can have zero or more fields of various types, and you can pattern match on the constructors to extract the data again.
19:23 <monochrom> http://haskelltools.org/
19:23 <Tuplanolla> My primary gripe is still the memory footprint. You can't easily predict that without testing the code extensively.
19:23 <Athas> ertes: I don't know, there have definitely been cases where I've found the Haskell ecosystem lacking in tools, despite my code base only being medium-sized.
19:23 <Cale> math493: So, for example, we can have a simple enumeration:
19:24 <Athas> Certainly, Haskell's properties make the lack of tooling far more tolerable.
19:24 <Cale> data Colour = Red | Green | Blue | White | Black
19:24 <Cale> Or something like a record:
19:25 <Cale> data Employee = MkEmployee String Integer
19:25 bhiliyam joined
19:25 <math493> What is MkEmployee here? :)
19:25 <monochrom> It is true that if you call "rename this thing" and "pull out that local definition" refactoring, that's quaint. But you still want a tool to do them for you.
19:25 <Cale> It becomes a function which takes a String and Integer, and constructs an Employee
19:25 <Cale> e.g. MkEmployee "John" 110000
19:25 <Cale> would have type Employee
19:26 <Cale> These types can also be parameterised by another type:
19:26 <Cale> data Either a b = Left a | Right b
19:26 <Cale> This one has two parameters
19:26 <math493> And there are 5 different colours? Does that mean it wouldn't have accepted "Yellow"? :)
19:26 <Cale> So a value of type Either Integer String
19:26 <Cale> right
19:26 <Cale> Red :: Colour
19:26 <ertes> math493: i suggest that you just learn the basics… they are easy enough to get into, before you get to the more advanced stuff
19:27 <Cale> etc.
19:27 <Cale> and those are the only values of type Colour
19:27 flatmap1_ joined
19:27 <ertes> math493: here is the definition of the Bool type: data Bool = False | True
19:27 <math493> ertes: I'm trying :)
19:27 <Cale> Right, Bool doesn't need to be built in, because we can define it :)
19:27 <ertes> a value of type Bool can be in one of two shapes: False and True
19:27 <math493> Cale: So no boolean exist already? :)
19:27 <ertes> nothing else is a Bool
19:27 <Squarism> ive done alot of java refactoring and one bigger in haskell - its was different nature. Where as java has extract method-or-variable/renames/introduce parameter/signature-change/pull-members - haskell constructors make it easier to do flow of control refactorings. (amatuer reflection). The haskell refactoring i did would prolly take longer in java.
19:28 <geekosaur> math493, that's what the Prelude is for
19:28 <ertes> Cale's Colour type follows the same logic
19:28 <ertes> Bool exists, but it's not built into the language… it comes with the base library
19:29 <Cale> So yeah, this data Either a b = Left a | Right b
19:29 <Cale> If I have something of type Either Integer String
19:29 <Cale> that means it's either of the form Left n where n has type Integer
19:29 <math493> ertes: You created a Bool type, but how would I use this type? :)
19:29 <Cale> or Right s where s has type String
19:29 <ertes> @let data MyBool = MyFalse | MyTrue deriving (Eq, Ord, Show)
19:29 <lambdabot> Defined.
19:29 <math493> Cale: That's nice :)
19:29 Itkovian joined
19:29 <ertes> @let myNot MyFalse = MyTrue; myNot _ = MyFalse
19:29 <lambdabot> Defined.
19:30 <ertes> @let boolsheet1 f = map f [MyFalse, MyTrue]
19:30 <lambdabot> Defined.
19:30 <ertes> > boolsheet1 myNot
19:30 <Cale> @let myAnd MyFalse _ = MyFalse; myAnd MyTrue x = x
19:30 <lambdabot> Defined.
19:30 <lambdabot> [MyTrue,MyFalse]
19:30 <Cale> > myAnd MyFalse MyTrue
19:30 <lambdabot> MyFalse
19:30 <Cale> > myAnd MyFalse (error "oops!")
19:30 <math493> Haha, I really like the lambdabot :D
19:30 <lambdabot> MyFalse
19:31 <Cale> ^^ it short circuits!
19:31 <monochrom> There is something wrong with how "boolsheet" pronounces like... :)
19:31 zeroed joined
19:31 <ertes> @let boolsheet2 f = map (\b -> map (f b) [MyFalse, MyTrue]) [MyFalse, MyTrue]
19:31 <lambdabot> Defined.
19:31 <ertes> > boolsheet2 myAnd
19:31 <lambdabot> [[MyFalse,MyFalse],[MyFalse,MyTrue]]
19:32 <math493> Why is the "deriving (Eq, Ord, Show)" part necessary?
19:32 <ertes> they're not, but they predefine certain functions like (==)
19:32 <Cale> That just makes the compiler write out a bunch of basic definitions for us
19:32 flump joined
19:32 <ertes> > MyTrue == MyTrue
19:32 <lambdabot> True
19:32 <math493> Nice :)
19:32 tathougies joined
19:32 dsh joined
19:32 <math493> Otherwise, it wouldn't have been possible to compare booleans?
19:32 <Cale> Right
19:32 <ertes> it would be, but you would have to write the code yourself =)
19:32 <Cale> Unless we explicitly added an instance of Eq for MyBool
19:33 <Cale> We could instead write
19:33 <Cale> instance Eq MyBool where
19:33 <Cale> MyTrue == MyTrue = True
19:33 <Cale> MyFalse == MyFalse = True
19:33 <Cale> _ == _ = False
19:33 mbrcknl joined
19:33 <ertes> the Show instance is particularly expensive to write by hand
19:33 <ertes> > show [Just MyTrue, Nothing]
19:33 <math493> ertes: Oh, that's a hardone? :)
19:33 <lambdabot> "[Just MyTrue,Nothing]"
19:33 <rightfold> not to mention Foldable
19:33 <math493> *hard one
19:34 <math493> Foldable? That's why you're called rightfold? :D
19:34 <ertes> it turns any haskell value into a readable string representation
19:34 <ertes> (quite literally Read-able)
19:34 <rightfold> rightfold is another name for foldr, which is a Haskell function
19:34 <ertes> > read (show True) :: Bool
19:34 <lambdabot> True
19:34 <math493> Cool :D
19:34 jorendorff joined
19:34 <ertes> @let deriving instance Read MyBool
19:34 <lambdabot> Defined.
19:35 <ertes> > read (show MyTrue) :: MyBool
19:35 <lambdabot> MyTrue
19:35 <pikajude> does lambdabot have type applications?
19:35 <ertes> that was a pretty-printer/parser round-trip
19:35 Itkovian joined
19:35 <ertes> > id @ Integer 5
19:35 <lambdabot> error:
19:35 <lambdabot> Pattern syntax in expression context: id@Integer
19:35 <lambdabot> Did you mean to enable TypeApplications?
19:35 <pikajude> nope
19:36 <Cale> math493: Anyway, a really important type in Haskell is of course the type of functions: if A and B are types, then A -> B is the type of functions which accept an argument of type A, and produce a result of type B
19:37 <Cale> math493: In Haskell, this is more meaningful than in most programming languages
19:37 <Cale> It really has to be a mathematical function
19:37 feepo joined
19:37 <math493> Cale: That sounds very mathematical :D
19:37 <ertes> math493: it *is* mathematical
19:37 <ertes> indeed, you can use equational reasoning in haskell, i.e. algebra
19:37 <Cale> i.e. if x = y then f x = f y
19:37 <Athas> Well, but every type is lifted, which is a little odd from a mathematical perspective...
19:37 <Cale> Athas: Not that odd :)
19:38 insitu joined
19:38 <Cale> math493: This makes things a lot easier to test in general
19:38 <math493> I see :)
19:38 <Cale> math493: You know that if a function produces some result in isolation, it'll produce the same result in production, when supplied with the same arguments
19:39 <ertes> math493: you can go as far as to set up a system of equations with some unknowns and solve for the unknowns in order to write code… but more importantly you can reason about your code *precisely*, in terms of algebra, not in terms of loose prose
19:39 <math493> That's a very nice property.
19:39 merijn joined
19:39 <Cale> math493: And you know for certain that the only things which can influence the result of the function are the values of those arguments
19:40 <math493> What was the purpose of these boolsheet1 and boolsheet2 again? Sorry, I know that we moved on, but I was just reading up and trying things out :)
19:40 <ertes> math493: that's why getLine is neither a function nor a string in haskell =)
19:40 <math493> :)
19:40 <Cale> It takes a while to relearn how to program under these restrictions, but once you do, it removes a huge burden in terms of how hard you have to think in order to understand programs.
19:40 <merijn> ski: wrt your comment earlier about using finally, that doesn't really make sense as then I'd either 1) double mask or 2) not properly unmask, since the code is already running inside mask
19:40 <math493> Cale: I'm sure it will take some time, but I intend to try :)
19:40 <ertes> math493: boolsheet2 f = [f MyFalse MyFalse, f MyFalse MyTrue, f MyTrue MyFalse, f MyTrue MyTrue]
19:41 <ertes> math493: boolsheet1 f = [f MyFalse, f MyTrue]
19:41 MarcelineVQ joined
19:41 <ertes> more conventionally called truth tables, but i like the word "bool sheet" =)
19:41 zar joined
19:41 <math493> Oh, it's a truth table :)
19:41 <ertes> oh, boolsheet2 was wrong
19:41 <ertes> boolsheet2 f = [[f MyFalse MyFalse, f MyFalse MyTrue], [f MyTrue MyFalse, f MyTrue MyTrue]]
19:42 <math493> ertes: By the way... if I may ask, how does it know that it should use the type Bool, if Bool isn't mentioned anywhere?
19:42 <Cale> ertes: Type inference :)
19:42 robkennedy joined
19:42 <ertes> math493: what Cale said =)
19:42 <Cale> If you use False and True, those can only be values of type Bool
19:43 ragepanda joined
19:43 <math493> Hm, but we don't. We use something called MyFalse and MyTrue - for some reason? Rather than False and True.
19:43 <Cale> Ah, yeah, those are values of type MyBool
19:43 <Cale> and the compiler knows that because we declared them to be such
19:43 <math493> Oh :)
19:43 <ertes> math493: type inference goes incredibly far in haskell… i don't expect you to understand how the following piece of code works, but it's the magic of type inference and type classes combined
19:44 <ertes> > sequence ["Hh", "e", "Ll", "l", "oO0"]
19:44 <lambdabot> ["HeLlo","HeLlO","HeLl0","Hello","HellO","Hell0","heLlo","heLlO","heLl0","he...
19:44 <Cale> heh, that's less impressive before you know anything about Monad
19:44 <orion> Hi. Let's say I have a banking service that allows customers who are programmers to script the authorization or denial of their credit card. I want them to submit raw code to me that I will run for every transaction. What are the pros/cons of allowing them to write Haskell in a restricted Monad vs. a Fre Monad DSL?
19:44 <math493> :D
19:45 <math493> Monads, is that a functional programming concept?
19:45 <orion> s/Fre/Free
19:45 <ertes> orion: one contra is that they might write really poor code that ends up eating your resources
19:45 <Cale> math493: Kinda
19:45 <ertes> orion: also, of course, you need proper sandboxing and Safe Haskell
19:46 ksj joined
19:46 <Cale> math493: It's originally from category theory, which is a branch of mathematics, and we stole it
19:46 cmsmcq joined
19:46 <Cale> math493: and you kind of need a language with a pretty decent type system to get any mileage out of it
19:46 <math493> Cale: I thought you were a mathematician? I recall that I've seen you in ##math sometimes :)
19:46 <ertes> math493: it's impossible to explain monads (in the context of haskell) at this point… you really need the language basics first
19:46 <Cale> (basically, you need type classes and type functions)
19:47 <cocreature> Cale is a magician that knows basically everything
19:47 <Cale> math493: I'm an applied logician who spends his time writing interesting proofs of trivial propositions in an inconsistent intuitionist logic.
19:47 <Cale> (i.e. Haskell)
19:47 <math493> Cale: Logician? I think Haskell was functional, not logic? You are probably also a Prolog programmer? :)
19:47 <Cale> (but yeah, I have a degree in pure mathematics)
19:48 <Cale> Ah, maybe I should bother explaining this
19:48 <ertes> math493: the only useful high-level overview i can think of is: "they are rich structure we can abstract over to get many things for free"
19:48 <Cale> heh
19:48 <Sornaensis> haskell supports type level programming
19:48 <Sornaensis> which is technically logic programming I think
19:48 <Cale> math493: I mean that Haskell's type system is itself structured similarly to a logic
19:48 <ertes> Sornaensis: if you do it in terms of instance resolution, yeah
19:48 <dmiles> isnt this type system some sort of OO?
19:48 <ertes> but you can also do it with type families, which is rather functional
19:48 <math493> Cale: Yeah :)
19:49 <* dmiles> ducks
19:49 <orion> ertes: Let's say for sake of argument that safe guards are in place.
19:49 <Cale> math493: In logic, if you want to prove A -> B (i.e. "A implies B") then you start by assuming A and trying to somehow conclude B, and if you succeed, by natural deduction you have A -> B
19:49 <math493> My programming lecturer was offering an elective course on term rewriting. He introduced it to convince us to take his course, but it didn't really work, when he started to talk about induction :D
19:49 <Cale> math493: In Haskell, if you want to write a function of type A -> B, you start by assuming you have a variable x of type A, and trying to construct a term y of type B
19:49 <Sornaensis> what's your day job Cale if I may ask
19:49 <Cale> math493: and if you succeed, you can write a lambda term (\x -> y) which is a function of type A -> B
19:50 <Cale> Sornaensis: I work for Obsidian Systems on web applications for various clients
19:50 <Cale> We use (and develop) the functional reactive programming system Reflex
19:51 <ertes> orion: well, by giving them haskell you give them general recursion anyway… so you need to guard against poor code quality
19:51 <Cale> Our web applications are pretty much 100% Haskell (with some bits of Javascript FFI thrown in here and there)
19:51 <Cale> (and some SQL)
19:51 <Sornaensis> :O
19:51 <Sornaensis> is reflex front end and back end?
19:52 <ertes> orion: also you need well written docs, because most of the customers likely won't be fluent in haskell
19:52 <monadicDuck> does anyone use spock + elm ?
19:52 <Cale> Frontend for now. I'd like to get some backend-related reflex stuff going
19:53 <Cale> But FRP is mostly well-suited to situations where you have a lot of complicated interactions between stateful things, and our backends are trying as far as possible to be stateless (though there is a bit of per-user state now)
19:53 <ertes> math493: i think what causes most people's brain to shut down is unfamiliar terminology and the associated math phobia it triggers, when in reality it's a really simple concept
19:53 <Cale> (well, "stateless" apart from the database ;)
19:53 flatmap13 joined
19:53 <math493> :D
19:53 <ertes> math493: i bet you have been doing some form of induction in your own code without knowing =)
19:53 <Sornaensis> do you use warp on the back end?
19:54 seveg joined
19:54 <Cale> Sornaensis: we're using Snap on the backend, actually, we do use Warp in the mobile frontend though
19:54 <math493> ertes: Really? I took a discrete mathematics course, which was mandatory, and I never really mastered induction... and I don't see the connection with code at all :D
19:55 <Sornaensis> how does Snap compare to Yesod?
19:55 <Cale> It's a bunch simpler, not so much template Haskell
19:55 <Cale> tbh, we're barely using Snap too
19:55 <ertes> Sornaensis: yesod is built on black boxes, whereas snap is fairly transparent
19:55 <Cale> Our applications are pretty much single page things which communicate over a websocket a bunch
19:55 <Sornaensis> heh
19:55 <Sornaensis> ah
19:56 <Sornaensis> single page that talks to a db?
19:56 <math493> > boolsheet2 myNot
19:56 <math493> Shouldn't this work?
19:56 <Cale> There's now some file streaming stuff in one of them
19:56 <Cale> yeah
19:56 <math493> > boolsheet2 myNot
19:56 <lambdabot> error:
19:56 <lambdabot> • Couldn't match type ‘MyBool’ with ‘MyBool -> b’
19:56 <lambdabot> Expected type: MyBool -> MyBool -> b
19:56 <math493> lambdabot is not happy
19:56 <Cale> math493: That one wants a function of two arguments
19:56 <Cale> :t boolsheet1
19:56 <lambdabot> (MyBool -> b) -> [b]
19:56 <Cale> :t boolsheet2
19:56 <lambdabot> (MyBool -> MyBool -> b) -> [[b]]
19:56 <math493> Oh, that's why
19:57 <math493> So I cannot give myNot to it?
19:57 <Cale> right
19:57 <ertes> math493: induction in general is the idea of a base case and a recursive case to cover something entirely
19:57 <math493> Hm, I don't think I have any function with two arguments
19:57 <ertes> math493: for example a list fold is inductive
19:57 <Cale> I defined myAnd earlier
19:57 <math493> Oh :)
19:57 <Cale> > boolsheet2 myAnd
19:57 <lambdabot> [[MyFalse,MyFalse],[MyFalse,MyTrue]]
19:57 <Cale> myAnd MyFalse _ = MyFalse; myAnd MyTrue x = x
19:57 <Cale> in case you missed it :)
19:57 <Cale> Note that it'll shortcut when defined like this
19:58 <ertes> math493: induction in proofs is not really different, except that you write proofs instead of values inductively
19:58 <Cale> > myAnd MyFalse undefined
19:58 <lambdabot> MyFalse
19:58 <Cale> undefined
19:58 <Cale> > undefined
19:58 <lambdabot> *Exception: Prelude.undefined
19:58 <Cale> undefined produces an exception if evaluated
19:59 <Sornaensis> > fst (1,undefined)
19:59 <lambdabot> 1
19:59 <Cale> So we can use it to observe when the value of something would need to be evaluated
19:59 <math493> Is boolsheet2 f = map (\b -> map (f b) [MyFalse, MyTrue]) [MyFalse, MyTrue] identical to boolsheet2 f = [[f MyFalse MyFalse, f MyFalse MyTrue], [f MyTrue MyFalse, f MyTrue MyTrue]]?
20:00 <Cale> yeah
20:00 <Sornaensis> :t (1, undefined)
20:00 <lambdabot> Num t1 => (t1, t)
20:00 fizruk joined
20:00 _Zianic joined
20:00 <ertes> math493: why don't you just try it? ;)
20:00 <orion> ertes: Sure. For the sake of this discussion, let's assume I have wonderful docs and a magical black box which can detect poor code.
20:00 <math493> ertes: I could of course :)
20:00 <ertes> @let boolsheet2' f = [[f MyFalse MyFalse, f MyFalse MyTrue], [f MyTrue MyFalse, f MyTrue MyTrue]]
20:00 <lambdabot> Defined.
20:01 <ertes> > boolsheet2 myAnd == boolsheet2' myAnd
20:01 <lambdabot> True
20:01 <ertes> or even…
20:01 <Cale> math493: So yeah, to move along with the demonstration of Haskell's type system, let's define a binary tree having values of some type a on the branch nodes
20:01 <ertes> @check \f -> boolsheet2 f == boolsheet2' f
20:01 <math493> Yeah :)
20:01 <lambdabot> error:
20:01 <lambdabot> • No instance for (CoArbitrary MyBool) arising from a use of ‘myquickcheck’ ...
20:01 <ertes> oh, of course…
20:02 <Cale> data Tree a = Tip | Branch a (Tree a) (Tree a)
20:02 <Cale> (and we can derive Eq, Ord, Show, etc. for this)
20:02 <math493> Oh, you can define trees in Haskell?
20:02 <Cale> yep
20:02 <ertes> math493: Cale just did =)
20:02 <Cale> So, this is our first example of recursion in a type
20:02 recycletrash joined
20:02 Gurkenglas joined
20:02 <math493> Are Branch and Tip built-in?
20:02 flatmap13 joined
20:03 <Cale> We define them by that line
20:03 <Cale> That line defines three things at once
20:03 <math493> Oh, that's also the definition of these :)
20:03 <Cale> The type Tree (which is actually a type level function, taking a type of values that the tree will carry)
20:03 <Cale> and then two data constructors
20:03 <Cale> Tip :: Tree a -- which has no arguments
20:04 <Cale> Branch :: a -> Tree a -> Tree a -> Tree a
20:04 flatmap1_ joined
20:04 <Cale> a function which takes a value of type a, and two subtrees
20:04 <ertes> math493: in words the line says: values of type (Tree a) are either of the shape Tip or of the shape (Branch x ls rs), where x is of type 'a' and ls and rs are of type (Tree a)
20:04 <Cale> @let data Tree a = Tip | Branch a (Tree a) (Tree a) -- will lambdabot let me define this, or am I going to have to rename it?
20:04 <lambdabot> .L.hs:167:25: error:
20:04 <lambdabot> Ambiguous occurrence ‘Tree’
20:04 <lambdabot> It could refer to either ‘Data.Tree.Tree’,
20:04 <Cale> yeah
20:05 <Cale> @let data BinTree a = Tip | Branch a (Tree a) (Tree a) -- will lambdabot let me define this, or am I going to have to rename it?
20:05 <lambdabot> Defined.
20:05 <Cale> oops
20:05 <Cale> hah
20:05 <Cale> @undefine
20:05 <lambdabot> Undefined.
20:05 <Cale> @let data BinTree a = Tip | Branch a (BinTree a) (BinTree a) -- will lambdabot let me define this, or am I going to have to rename it?
20:05 <lambdabot> Defined.
20:05 <Cale> okay
20:05 <Cale> heh, could've removed the comment on that last one
20:05 <Cale> > Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip)
20:05 <lambdabot> error:
20:05 <lambdabot> • No instance for (Show (BinTree a0))
20:05 <lambdabot> arising from a use of ‘show_M309630444005167036127282’
20:05 <Cale> no show yet
20:05 ForgedPancake joined
20:06 <math493> :D
20:06 <Cale> @let deriving instance Show a => Show (Tree a)
20:06 <ertes> would be nice, if lambdabot had per-user modules
20:06 <lambdabot> .L.hs:162:1: error:
20:06 <lambdabot> Duplicate instance declarations:
20:06 <lambdabot> instance [safe] Show a => Show (Tree a) -- Defined at .L.hs:162:1
20:06 <Cale> @let deriving instance Show a => Show (BinTree a)
20:06 <lambdabot> Defined.
20:06 <ertes> but as we all know…
20:06 <ertes> @src blah
20:06 <lambdabot> Source not found. Do you think like you type?
20:06 <ertes> lambdabot is not nice =)
20:06 <Sornaensis> Data.Tree.Tree.Lazy.Tree.Tree.Strict
20:06 <Tuplanolla> Would be nice if lambdabot even had sane imports.
20:06 <Cale> How can I explain to Sigyn that I'm not a spammer?
20:06 niteria joined
20:06 <Sornaensis> :list
20:06 <Sornaensis> @list
20:06 <lambdabot> What module? Try @listmodules for some ideas.
20:07 <math493> Sigyn? :D
20:07 <Cale> My messages are tripping anti-spam measures, apparently. If I get k-lined, that'll be why.
20:07 <math493> Haha :D
20:08 <Cale> anyway, let's write some functions on this tree type
20:08 <merijn> Cale: What do you mean?
20:08 <Cale> merijn: I got a NOTICE from Sigyn saying that my actions in #haskell tripped automated anti-spam measures, but were ignored based on time in channel, and asking me to stop.
20:09 <merijn> Maybe ask about that in #freenode?
20:09 <MarcelineVQ> :>
20:09 <ertes> you could report that in #freenode or something
20:09 <math493> Is Sigyn some bot?
20:09 <math493> https://pastebin.com/sSmtrnCi - why does that not work? Isn't it just what Cale did here?
20:09 flatmap13 joined
20:10 <ertes> math493: :seti -XStandaloneDeriving
20:10 <ertes> lambdabot has that extension enabled by default
20:10 <math493> ertes: Oh :)
20:10 <Cale> math493: You could also include the deriving as part of the data declaration, I just did it that way because I forgot tbh
20:10 <math493> I just wanted to try to reproduce it :)
20:10 <ertes> "seti" = "set for interactively written code"
20:10 <math493> :)
20:11 <ertes> nothing with extra-terrestrials
20:11 dfeuer joined
20:11 dsh joined
20:11 <Sornaensis> > System.IO.Unsafe.unsafeCoerce 'a' :: Int
20:11 <lambdabot> error:
20:11 <lambdabot> Not in scope: ‘System.IO.Unsafe.unsafeCoerce’
20:11 <lambdabot> No module named ‘System.IO.Unsafe’ is imported.
20:11 <math493> Cale: Hm, so would something like data BinTree a = Tip | Branch a (BinTree a) (BinTree a) deriving instance Show a => Show (BinTree a) be OK?
20:11 <math493> [22:11] -Sigyn- Your actions in #haskell tripped automated anti-spam measures, but were ignored based on your time in channel; stop now, or automated action will still be taken. If you have any questions, please don't hesitate to contact a member of staff
20:12 <math493> Hm...
20:12 <ertes> Tip Branch BinTree
20:12 <jle`> Sornaensis: not quite the right module, even if it was allowed :)
20:12 <ertes> data tip branch bintree instance show
20:12 <mniip> too late
20:12 <mniip> it is gone
20:13 shayan_ joined
20:13 <math493> ertes: Hm, where?
20:13 <ertes> math493: where what?
20:13 <ertes> math493: i was just trying to trigger Sigyn
20:13 <math493> ertes: Where would I write "Tip Branch BinTree"?
20:13 <math493> Oh :)
20:13 <ski> Sigyn is a bot, yes
20:14 <mniip> ertes, it was /(bintree a)/
20:14 <Cale> Okay, staff cleared the temp patterns for #haskell, we're safe for now
20:14 <math493> :D
20:14 <ertes> but apparently Sigyn loves me… at least more than lambdabot does =)
20:15 <math493> [22:11] <math493> Cale: Hm, so would something like data BinTree a = Tip | Branch a (BinTree a) (BinTree a) deriving instance Show a => Show (BinTree a) be OK?
20:15 <ertes> mniip: that's a weird thing to trigger it
20:15 Rodya_ joined
20:15 <Cale> math493: data BinTree a = Tip | Branch a (BinTree a) (BinTree a) deriving (Eq, Ord, Show)
20:15 <mniip> ertes, it learns from live data *shrug*
20:15 <Cale> (or you can just put Show in there)
20:15 <math493> Oh :)
20:16 <math493> Nice :)
20:16 <nbro> so, tell me, what is the angriest guy in this group?
20:16 <ertes> the wonders of machine learning =)
20:16 <ertes> nbro: mauke
20:16 <nbro> last time there was a person that kicked me because I said I would have asked one thing in this group
20:16 <math493> Now we defined a binary tree? Can we use it in some way? :)
20:16 <nbro> and I did not even talk
20:16 <nbro> no
20:16 <Cale> math493: sure
20:16 <nbro> it’s not mauke
20:16 <nbro> there’s another
20:16 <nbro> but I do not remember the name
20:16 <nbro> completely mad person
20:16 <* ski> has noticed Sigyn accidentally three times
20:17 <Cale> @let treeDepth Tip = 0; treeDepth (Branch _ l r) = 1 + max (treeDepth l) (treeDepth r)
20:17 <lambdabot> Defined.
20:17 <ertes> nbro: /query lambdabot, then type: @where ops
20:18 <ertes> (don't do it in the channel, please)
20:18 <Cale> @let treeSum Tip = 0; treeSum (Branch x l r) = x + treeSum l + treeSum r
20:18 <lambdabot> Defined.
20:18 <nbro> I think it was dibblego
20:18 <nbro> omg
20:18 <nbro> that guy
20:18 zar joined
20:18 <Cale> > treeDepth (Branch 1 (Branch 2 (Branch 3 Tip Tip) Tip) (Branch 4 Tip (Branch 5 Tip Tip)))
20:18 <lambdabot> 3
20:18 <Cale> > treeSum (Branch 1 (Branch 2 (Branch 3 Tip Tip) Tip) (Branch 4 Tip (Branch 5 Tip Tip)))
20:19 <lambdabot> 15
20:19 <math493> Hm, how do I see that the depth of the tree is 3?
20:19 <dolio> nbro: I'm not impressed with your behavior so far this time.
20:19 <Cale> Well, you could try drawing a picture of it. The root node is the one labelled with 1
20:20 <Cale> it has a left subtree labelled 2, which has a left subtree labelled 3
20:20 <mniip> > treeDepth (fix $ join $ Branch ())
20:20 <ertes> @let treeFold _ t Tip = t; treeFold b t (BinTree x ls rs) = b x (treeFold b t ls) (treeFold b t rs)
20:20 <lambdabot> .L.hs:168:15: error: Not in scope: data constructor ‘BinTree’
20:20 <lambdabot> *Exception: stack overflow
20:20 <nbro> dolio: what?
20:20 <jle`> @let appendTree Tip = id; appendTree (Branch x l r) = appendTree l . (x:) . appendTree r
20:20 <lambdabot> Defined.
20:20 <ertes> @let treeFold _ t Tip = t; treeFold b t (Branch x ls rs) = b x (treeFold b t ls) (treeFold b t rs)
20:20 <lambdabot> Defined.
20:21 <Cale> ertes already abstracting over my recursion ;)
20:21 <* geekosaur> agrees with dolio
20:21 <jle`> > appendTree (Branch 1 (Branch 2 (Branch 3 Tip Tip) Tip) (Branch 4 Tip (Branch 5 Tip Tip))) []
20:21 cmsmcq joined
20:21 <lambdabot> [3,2,1,4,5]
20:21 <ertes> @let treeDepth' = treeFold (\x sl sr -> 1 + max sl sr) 0
20:21 <lambdabot> Defined.
20:21 <geekosaur> also I just found the log in question and you had been trolling in #scala and threatened to spread it to #haskell, so popping into #haskell immediately afterward was not the wisest of ideas
20:22 <math493> Hm, I find it a bit hard to imagine what (Branch 1 (Branch 2 (Branch 3 Tip Tip) Tip) (Branch 4 Tip (Branch 5 Tip Tip))) would look like :)
20:22 <ertes> > treeDepth (Branch () (Branch () Tip Tip) Tip)
20:22 <lambdabot> 2
20:22 <ertes> > treeDepth' (Branch () (Branch () Tip Tip) Tip)
20:22 <lambdabot> 2
20:22 <Cale> math493: Well, Branch x l r means a branch node labelled x, with l and r as its left and right subtrees
20:22 <Cale> math493: and Tip represents an unlabelled leaf (which we're regarding as having depth 0)
20:23 <Cale> i.e. the empty tree
20:23 <math493> So (Branch 2 (Branch 3 Tip Tip) Tip) is left subtree and (Branch 4 Tip (Branch 5 Tip Tip)) is right subtree of the root?
20:23 <Cale> yeah
20:23 sleffy joined
20:23 <math493> And these again have subtrees? :)
20:23 <Cale> yeah, the one labelled 2 at the root has (Branch 3 Tip Tip) as its left subtree
20:23 <Cale> and Tip as its right
20:24 <Cale> The one labelled 4 has Tip as its left subtree, and (Branch 5 Tip Tip) as its right
20:24 <Philonous> I have an API-design question: I'm working on a function in a dbus package that returns values received via dbus. Is it better to just return the unmarshalled values (and leave conversion to the user), convert according to a type class (which mean type annotations are sometimes necessary) or convert to a fixed set of Haskell types (arbitrary and makes it less convenient to marshal other types)
20:24 <math493> Cale: I only have Paint to draw, so it's not pretty, but does it look like this? http://imgur.com/a/lwivB
20:25 <merijn> Philonous: Why not combine options? Implement option 1) raw unmarshalled values and implement a convenience type class based one on top of that?
20:25 <Cale> math493: sort of, but depending on how you're drawing tips, it should look a little different
20:25 bhiliyam joined
20:26 <math493> Is a tip what we usually call a leaf?
20:26 <Philonous> merijn, I guess that makes sense. It's what I have now
20:26 MrWoohoo joined
20:26 <ski> a tip is like a leaf, but without a value
20:26 iAmerikan joined
20:27 <Philonous> The one I'm using most myself is a combination of the type class and a newtype + type family that fixes the return types (so no type annotations), I just have to write "R val <- call «...»" all the time (but that's better than having to write types)
20:28 <ertes> Philonous: the aeson library does something similar: provide a type for generic JSON values (Value), parse into that, then provide type classes to go from that to other haskell types and back
20:29 cdg joined
20:29 <Cale> math493: http://cale.hn.org/share/tree.png
20:29 <Cale> math493: yeah
20:29 <ertes> Philonous: and instances can be written using generics, so it's pretty much completely automatic, if you want it to be
20:29 Bob8989|2 joined
20:29 <Cale> math493: Though usually I'll use the word "Leaf" when there's actually data there too
20:29 <math493> Cale: Oh :)
20:29 <Philonous> ertes, I have TH that generates instances
20:30 <math493> Cale: More pretty than this: http://imgur.com/a/9K9jF (that would have been my second guess)
20:30 <Cale> math493: depending on how you think about it, perhaps 3 and 5 are leaves
20:30 <Cale> yeah, that's right
20:30 <Philonous> merijn, ertes thanks
20:30 xcin joined
20:30 <ertes> Philonous: i understand your suffering, but you can always just switch to generics =)
20:30 <math493> But mine is not that pretty :D
20:30 <Cale> inkscape :D
20:30 <math493> :D
20:31 <Philonous> ertes, I actually don't mind writing TH too much
20:31 <nbro> @let x = [1..]
20:31 <lambdabot> Defined.
20:31 <nbro> > x
20:31 <lambdabot> error:
20:31 <lambdabot> Ambiguous occurrence ‘x’
20:31 <lambdabot> It could refer to either ‘Debug.SimpleReflect.x’,
20:31 <Cale> > L.x
20:31 <lambdabot> [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,...
20:31 fizbin joined
20:31 <math493> But what was the treeSum doing? The sum of what? Like sum [1..5]?
20:31 takle joined
20:31 <Cale> yeah, the sum of the elements of the tree
20:31 jchia joined
20:31 serendependy joined
20:31 <math493> Cale: These can be seen as values in the nodes?
20:31 anuxivm joined
20:31 <Cale> We said that treeSum Tip = 0, i.e. the sum of an empty tree is 0 (since that's the identity for addition)
20:32 <Cale> and then that treeSum (Branch x l r) = x + treeSum l + treeSum r
20:32 <Cale> i.e. we add x to the sum of the left and right subtrees
20:32 <math493> That's nice :)
20:32 <math493> You are a great teacher.
20:32 darthvorik_ joined
20:32 <nbro> thanks!
20:33 <Cale> thanks!
20:33 <math493> :D
20:33 <Sornaensis> herr herr
20:34 <Cale> Let's take a look at the type of treeDepth and treeSum
20:34 <Cale> :t treeDepth
20:34 bennofs joined
20:34 <lambdabot> (Num t, Ord t) => BinTree t1 -> t
20:34 darlan joined
20:34 <Cale> This was inferred by the compiler since I didn't specify it
20:34 <math493> [22:20] <ertes> @let treeFold _ t Tip = t; treeFold b t (Branch x ls rs) = b x (treeFold b t ls) (treeFold b t rs)
20:34 <math493> What was this again? :)
20:34 <math493> Some abstraction?
20:34 <Cale> Let's get to that in a moment
20:34 <Cale> yeah, it abstracts over the pattern in treeSum and treeDepth
20:34 unK_ joined
20:35 <math493> :)
20:35 <Cale> Basically, it expresses the idea that we're replacing each Tip in the tree with some value t
20:35 <Cale> and each Branch with some function b
20:35 <ertes> @let treeFoldl' f s0 xs0 = treeFold (\x ls rs s'' -> let !s' = ls s''; !s = rs s' in f s x) id xs0 s0
20:35 <lambdabot> Defined.
20:35 <ertes> :t @treeFoldl' (+) 0
20:35 <lambdabot> error: parse error on input ‘@’
20:35 <Cale> heh
20:35 <ertes> :t treeFoldl' (+) 0
20:35 <lambdabot> Num t1 => BinTree t1 -> t1
20:35 <Cale> Let's just start with treeFold directlyu
20:36 indi_ joined
20:36 <nbro> @let lambdabot = "stupid"
20:36 <lambdabot> Defined.
20:36 <nbro> ahah
20:36 <nbro> stupid bot
20:36 <Cale> nbro: btw, you can talk to the bot in private
20:36 <nbro> > lambdabot
20:36 <lambdabot> "stupid"
20:37 <nbro> Cale: yeah, I know
20:37 MrRicecake joined
20:37 <Cale> nbro: Please try to keep your signal to noise ratio higher.
20:37 dstockwell joined
20:37 <Cale> anyway
20:37 <ertes> math493: i have a fairly long and comprehensive tutorial on list folds, if you're interested… treeFold is pretty much the same idea, but for trees
20:37 <nbro> Cale: I will try to make things better in the future
20:37 <nbro> np
20:38 <nbro> or
20:38 <nbro> p
20:38 <nbro> who knows?!
20:38 <math493> I'll be happy to read it later :)
20:38 <Cale> math493: You can see that in treeSum, we're effectively replacing each Tip with 0, and the function Branch with (\x l r -> x + l + r) throughout the tree
20:38 <ertes> math493: it's here: http://ertes.eu/tutorial/foldr.html
20:38 <math493> Thanks, ertes
20:38 <math493> Cale: So now the tips are turned into leaves?
20:39 <Cale> math493: Well, the trees are all turned into numbers
20:39 g0d355__ joined
20:40 <Cale> math493: So, each Tip becomes the number 0, and at each Branch, instead of forming a tree, we want to add up the given value with the values from the subtrees
20:40 thatguyfrombefor joined
20:40 <Cale> (which will be numbers, once we do all this replacing)
20:40 <math493> Cale: So basically, we follow a path? From root to tip?
20:41 zar joined
20:41 <Cale> Given a data type defined in the way we've been seeing, it's often the case that it's handy to define a function which will take replacements for each of the data constructors we introduced, and make those substitutions throughout a data structure
20:41 <math493> I can imagine that :)
20:41 <Cale> I'm going to do it a little differently from ertes, but it'll amount to the same thing:
20:42 <* ski> . o O ( algebra )
20:42 <Cale> ski: Well, more similar than that, I'm basically writing the same thing, just a little differently
20:43 <Cale> @let treeCata tip branch = g where g Tip = tip; g (Branch x l r) = branch x (g l) (g r)
20:43 <lambdabot> Defined.
20:43 <Cale> So, this is a function which, given some values tip and branch, produces the function g
20:43 <merijn> Is it me or is criterion overly dramatic with it's "severely inflated" remark about variance introduced by outliers?
20:43 bjz joined
20:43 <Cale> and what g does is to replace each occurrence of Tip with tip
20:43 <Cale> and each occurrence of Branch with branch, throughout the whole tree
20:43 Itkovian joined
20:44 <merijn> I have a 129 ns average with (124.5 ns min and 134.7 ns max) and it reports variance introduced by outliers: "92% (severely inflated)"
20:44 <monochrom> merijn: I don't know, but keep repeating until the variance is small :)
20:44 recycletrash joined
20:44 <math493> Oh :)
20:44 <Cale> merijn: That means it's 92% higher variance than there would be if there were no outliers
20:44 <merijn> monochrom: Isn't that what it's supposed to do autmatically
20:45 <ertes> merijn: that could mean that there are almost no points near the line
20:45 <merijn> ertes: ?
20:45 <monochrom> OK I was joking.
20:45 <math493> Cale: What are tip and branch? Something very similar to Tip and Branch?
20:45 <Cale> math493: Well, they're the arguments to treeCata
20:45 <monochrom> But the range 124-134 doesn't look all that bad.
20:45 <merijn> monochrom: Hence my confusion
20:45 <ski> they're what we're replacing the data constructors `Tip' and `Branch' with
20:46 <math493> Oh, so they could be numbers?
20:46 zar joined
20:46 <Cale> math493: So we get to plug in whatever we want there
20:46 <Cale> :t treeCata
20:46 <monochrom> May it be true that the range 124-134 does not include outliers?
20:46 <lambdabot> t1 -> (t -> t1 -> t1 -> t1) -> BinTree t -> t1
20:46 <merijn> monochrom: No idea
20:46 <Cale> We can choose t1 and t to be whatever types we want
20:46 <Cale> So, if we have a BinTree Integer, for example
20:46 <ski> so that `treeCata tip branch' applied to `Branch 0 (Branch 1 Tip Tip) (Branch 2 (Branch 3 Tip Tip) Tip)' will be `branch 0 (branch 1 tip tip) (branch 2 (branch 3 tip tip) tip)'
20:46 <Cale> and we want to add everything up
20:46 <Cale> We might choose t1 = Integer as well
20:47 <Cale> So tip would be an Integer in that case
20:47 <math493> Nice, it's very flexible :)
20:47 <Cale> and branch would be a function which takes three Integer values and somehow combines them
20:47 <Cale> (the value at the root, and the values obtained by collapsing the left and right subtrees in this way)
20:47 Jackneill joined
20:47 <ski> `branch' must be a function of type `t -> t1 -> t1 -> t1', `t' being the element type in the tree, and `t1' the "final answer" type that we'd like to get in the end. `tip' must also be of type `t1'
20:47 wroathe joined
20:48 <Cale> :t treeCata Tip (\x l r -> Branch x r l)
20:48 <lambdabot> BinTree a -> BinTree a
20:48 revprez_atlanta joined
20:48 <Cale> ^^ this function will flip a binary tree over left to right
20:48 <ski> @type treeCata Tip Branch
20:48 <lambdabot> BinTree a -> BinTree a
20:48 <Cale> ^^ and that one does nothing :)
20:48 <nbro> :)
20:48 <math493> Hm, why is it interesting, if it does nothing? :D
20:49 <nbro> it’s inert
20:49 <Cale> Because it's a starting point
20:49 <math493> Oh, you're extending it :)
20:49 <Cale> for thinking about what treeCata does in general
20:49 <nbro> the craft of being lazy
20:50 <ertes> merijn: well, if your algorithm always takes 100 ns or 200 ns, then the mean will be 150 ns, and it will report "severely inflated"
20:50 <Cale> > treeCata Tip (\x l r -> Branch (10*x) l r) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip))
20:50 <lambdabot> Branch 10 (Branch 20 Tip Tip) (Branch 30 Tip Tip)
20:50 <ertes> merijn: that's how i understand it
20:50 <Cale> ^^ here's an example of applying a function to all the elements in the tree
20:50 <merijn> ertes: I'm benchmarking messy IO stuff, so it's going to be noisy regardless
20:50 <math493> Cale: That's nice! :D
20:50 <Cale> > treeCata 0 (\x l r -> 1 + max l r) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip)) -- tree depth again
20:50 <lambdabot> 2
20:51 <ski> > treeCata [] (\a l r -> a : l ++ r) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip))
20:51 <lambdabot> [1,2,3]
20:51 <Cale> ^^ preorder traversal
20:51 <math493> [22:50] <@Cale> > treeCata Tip (\x l r -> Branch (10*x) l r) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip))
20:51 <math493> So as first argument, you just write... Tip?
20:51 fotonzade joined
20:51 <Cale> yeah
20:51 <ski> replacing the empty tree with itself
20:51 <math493> Cale: Because it's unmodified?
20:51 <Cale> yeah
20:51 <ski> yep
20:52 <math493> I really like these Haskell examples.
20:52 <ski> @type treeCata Tip
20:52 <lambdabot> (t -> BinTree a -> BinTree a -> BinTree a) -> BinTree t -> BinTree a
20:52 <nbro> :k treeCata
20:52 <lambdabot> error: Not in scope: type variable ‘treeCata’
20:52 <nbro> ok
20:52 <mniip> :t fix (`treeCata` id)
20:52 <lambdabot> error:
20:52 <lambdabot> • Occurs check: cannot construct the infinite type:
20:52 <lambdabot> t1 ~ BinTree (t1 -> t1 -> t1) -> t1
20:52 <Cale> :k BinTree
20:52 <lambdabot> * -> *
20:52 <mniip> hum
20:53 <dfeuer> edwardk: ping
20:53 <ertes> @let treeAna f = go where go = maybe Tip (\(x, sl, sr) -> Branch x (go sl) (go sr)) . f
20:53 <lambdabot> Defined.
20:53 <Cale> math493: Now, something to notice... let's drop back to a simpler example of a type
20:53 <Cale> :t map
20:53 <lambdabot> (a -> b) -> [a] -> [b]
20:53 JagaJaga joined
20:53 <math493> Yeah :)
20:53 <Cale> Or indeed, we could do this for BinTree:
20:54 <Cale> :t (\f -> treeCata Tip (Branch . f))
20:54 <lambdabot> (a1 -> a) -> BinTree a1 -> BinTree a
20:54 <Cale> but anyway
20:54 <nbro> very interesting that I’m almost reaching a climax
20:54 <Cale> something to observe is that just based on the type
20:54 <mniip> :t fix . flip (flip treeCata id) x
20:54 <lambdabot> error:
20:54 <lambdabot> Ambiguous occurrence ‘x’
20:54 <lambdabot> It could refer to either ‘Debug.SimpleReflect.x’,
20:54 <mniip> :t fix . flip (flip treeCata id)
20:54 <lambdabot> BinTree (c -> c -> c) -> c
20:54 <mniip> there we go
20:54 <Cale> We can tell that any value occurring in the resulting data structure *must* have come from applying the given function to a value which was in the input structure
20:55 <dfeuer> Cale: what do you think? Should the Strong class have a method lensical :: (s -> a) -> (s -> b -> t) -> p a b -> p s t ?
20:55 <math493> Cale: Wow, that's really nice :)
20:55 <Cale> dfeuer: No opinion, I've never used that class.
20:55 <Cale> math493: So if you write the type signature up front, the compiler almost won't let you screw up
20:56 <ski> > snd (treeCata (\i -> (i,Tip)) (\a i_l i_r i0 -> let (i1,l) = i_l (i0 + 1); (i2,r) = i_r i1 in (i2,Branch (i0,a) l r)) (Branch 'a' (Branch 'b' Tip Tip) (Branch 'c' Tip Tip)) 0) -- a bit hard to follow ..
20:56 <lambdabot> Branch (0,'a') (Branch (1,'b') Tip Tip) (Branch (2,'c') Tip Tip)
20:56 <dfeuer> Cale: me neither, but it seems like it should be; avoid the tupling, and win defaults for dimap and also the other Strong methods.
20:56 <Cale> You might end up writing something which transforms the structure inappropriately, but that's almost harder than doing the right thing
20:56 <mniip> :t fix . flip (`treeCata` Branch)
20:56 <mniip> theeeere we go
20:56 <lambdabot> BinTree a -> BinTree a
20:56 <Cale> dfeuer: It can be inter-defined with the existing methods, right?
20:56 <dfeuer> Cale: yes.
20:56 <Cale> dfeuer: do it then :)
20:57 <dfeuer> Cale: not going to be up to me! But I'll submit the PR.
20:57 <math493> Cale: I'm sure that's useful in larger programs :)
20:57 <Cale> math493: Yeah, the effect that this kind of thing can have over a large codebase is great
20:57 biglambda joined
20:57 <math493> Does people also write Haskell programs, which are like... thousands of lines?
20:57 <Cale> Yeah, most of the projects I'm working on these days are at least a few thousand lines, if not in the tens of thousands
20:57 <mniip> they are always refactored to 1 line
20:58 <dfeuer> Cale: tens of thousands of lines of Haskell?
20:58 <math493> Wow :O
20:58 <dfeuer> That sounds ... enormous.
20:58 binaryplease joined
20:58 <Cale> nbro: Well, the open sourced part is basically reflex-platform for now.
20:58 <ski> dfeuer : hmm .. somehow reminds me of Dialectica
20:58 <monochrom> But 1000 lines of Haskell may very well replace 5000 lines of other languages.
20:58 <dfeuer> ski: what be that?
20:59 <Cale> One thing we're doing for a client is intended to become a competitor to Slack with a bunch of additional features
20:59 ChaiTRex joined
20:59 <Cale> like integration with email (you can send an email from a channel and replies to the email will return to that channel)
20:59 <ski> dfeuer : <https://en.wikipedia.org/wiki/Dialectica_space>
20:59 RonnieHolm joined
21:00 davean joined
21:00 <monochrom> Also bear in mind that Cale's employer has been operating for a few years. It got to build up that much code (and good code).
21:00 <dfeuer> ski, that be way over my 'ead.
21:00 <mniip> 1000 lines of haskell isn't that many really
21:00 <dfeuer> This is based on something phadej wrote, IIRC.
21:00 <dfeuer> Yes.
21:00 <dfeuer> BTW, is phadej here?
21:01 <mniip> * [phadej] idle 34:08:59
21:01 <math493> [22:51] <ski> > treeCata [] (\a l r -> a : l ++ r) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip)) - this was preorder traversal, right? :)
21:01 RonnieHo` joined
21:01 <Cale> yeah
21:01 <hexagoxel> pandoc is 48k loc judging by simple wc -l
21:01 <dfeuer> mniip: how discovered that you did?
21:01 <mniip> /whois
21:01 <Cale> That preorder traversal has a subtle performance problem though
21:01 wroathe joined
21:01 <ski> mniip : as Cale said, yes
21:01 <ski> er ..
21:01 RonnieHo` left
21:01 <ski> math493 ^
21:01 <Cale> The problem is that xs ++ ys takes O(length xs) steps to evaluate
21:02 <math493> Oh... but well, for toy examples... :)
21:02 <Cale> and so that will result in quadratic time, for leftward leaning trees
21:02 <Cale> There's a standard trick we can use to fix it though
21:02 RonnieHolm left
21:02 <math493> Oh, it's probably simple?
21:02 <mniip> oh oh oh is it hughes lists
21:02 <math493> I mean, this is more "proof-of-concept" :)
21:02 <Cale> Which is, instead of producing a list of type [a], we will produce a function of type [a] -> [a]
21:02 <Cale> which adds elements to the beginning of any list we give it
21:03 <Cale> Then [] will become id (the identity function, which adds no elements)
21:03 <ski> instead of producing `[0,1,2]' we produce `\ns -> 0 : 1 : 2 : ns'
21:03 <Cale> and the one element list [x] will become (x:) -- the function which adds x to the beginning of alist
21:03 <Cale> a list*
21:03 robotroll joined
21:03 <math493> Oh :)
21:03 <Cale> and lastly, and most importantly (++) will become (.) -- function composition
21:03 <Cale> Function composition is O(1)
21:03 eacameron joined
21:03 Nicmavr joined
21:04 <Cale> So this will asymptotically improve the performance, and then we can apply the resulting function to an empty list at the end
21:04 <math493> I see, that's nice :)
21:04 <Cale> :t treeCata id (\x l r -> (x:) . l . r)
21:04 <lambdabot> BinTree a -> [a] -> [a]
21:04 ronnie joined
21:04 <Cale> :t treeCata id (\x l r -> (x:) . l . r) []
21:04 <lambdabot> error:
21:04 <lambdabot> • Couldn't match expected type ‘BinTree a’ with actual type ‘[t0]’
21:04 <lambdabot> • In the third argument of ‘treeCata’, namely ‘[]’
21:04 <Cale> oops
21:04 <Cale> right
21:04 <Cale> :t \t -> treeCata id (\x l r -> (x:) . l . r) t []
21:04 <lambdabot> BinTree a -> [a]
21:04 vaibhavsagar joined
21:05 <Cale> that's pre-order
21:05 {emptyset} joined
21:05 <Cale> :t \t -> treeCata id (\x l r -> l . (x:) . r) t []
21:05 <lambdabot> BinTree a -> [a]
21:05 <Cale> in-order
21:05 <mniip> preorder as in entry time order?
21:06 <Cale> As in, the root comes before everything else
21:06 ericdwhite joined
21:06 <ski> as in node element listed before / to the left of elements of children
21:06 mulk joined
21:06 <mniip> never heard of this word being used in this context before
21:06 <Cale> pre-order, in-order, post-order
21:06 <math493> mniip: It's standard terminology
21:07 <ertes> @let testTree = > treeAna (\g' -> let (x, g) = randomR (0, 100000 :: Integer) g'; (gl, gr) = System.Random.split g in do guard (x /= 1); pure (x, gl, gr)) (mkStdGen 50)
21:07 <lambdabot> Parse failed: Parse error: >
21:07 <ertes> @let testTree = treeAna (\g' -> let (x, g) = randomR (0, 100000 :: Integer) g'; (gl, gr) = System.Random.split g in do guard (x /= 1); pure (x, gl, gr)) (mkStdGen 50)
21:07 <lambdabot> Defined.
21:07 <ertes> you can stop writing those long literals by hand now =)
21:07 <ertes> > testTree
21:07 <Cale> hah
21:07 <lambdabot> Tip
21:07 <Cale> hahaha
21:07 <ertes> you gotta be joking…
21:07 <math493> Cale: What you did, was that some general pattern? You didn't do traversal of specific trees, did you?
21:07 <ertes> > treeAna (\g' -> let (x, g) = randomR (0, 100000 :: Integer) g'; (gl, gr) = System.Random.split g in do guard (x /= 1); pure (x, gl, gr)) (mkStdGen 100)
21:08 <lambdabot> Branch 681 (Branch 78924 (Branch 31528 (Branch 79033 (Branch 23754 (Branch 5...
21:08 <ertes> seriously?
21:08 darjeeling_ joined
21:08 <Cale> math493: That only applied to our BinTree type that we defined earlier
21:08 ragepanda joined
21:08 Berra joined
21:08 <ertes> i picked the one seed out of 100000 that produces a Tip
21:08 <Cale> math493: But these ideas, like defining a function which does that substitution of constructors, tend to be often useful for many types
21:09 flump joined
21:09 Habib joined
21:09 RonnieHolm joined
21:09 <Cale> math493: The functions I wrote will work for any BinTree though, no matter what the element type is
21:09 <Cale> math493: and moreover, the type signature that the compiler inferred lets us know that it doesn't fiddle with the elements at all
21:09 <math493> Cale: So if I wanted to do pre-order traversal of (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip)) using your functions, how would I do that? :)
21:10 <Cale> > (\t -> treeCata id (\x l r -> (x:) . l . r) t []) (Branch 1 (Branch 2 Tip Tip) (Branch 3 Tip Tip))
21:10 <Habib> Hey, does anyone here know how common it is to use a PaaS like Heroku for Haskell-based cloud projects?
21:10 <lambdabot> [1,2,3]
21:10 <ski> > foldr (\n c_ns c -> c_ns (c . (n :) . c)) (\c -> c []) "abcd" id
21:10 <math493> Nice :)
21:10 <lambdabot> "abacabadabacaba"
21:10 <Cale> math493: Going back to lists, foldr is the function which does this replacement of constructors for a list
21:10 <ertes> > take 4 . drop 8 $ foldr (\n c_ns c -> c_ns (c . (n :) . c)) (\c -> c []) "abcd" id
21:10 <lambdabot> "abac"
21:11 <ertes> > take 4 . drop 10 $ foldr (\n c_ns c -> c_ns (c . (n :) . c)) (\c -> c []) "abcd" id
21:11 <ski> > foldr f z [a,b,c,d]
21:11 <Cale> Every list in Haskell is either the empty list [], or it is a nonempty list formed as x : xs from an initial element x and some tail xs
21:11 <lambdabot> "acab"
21:11 <lambdabot> f a (f b (f c (f d z)))
21:11 <Cale> (which is another list)
21:11 <Cale> foldr f z is the function which replaces each (:) in the construction of a list with f, and the [] at the end (if any) with z
21:11 <Cale> > foldr f z [1,2,3] -- magic
21:11 wroathe joined
21:11 <lambdabot> f 1 (f 2 (f 3 z))
21:11 <ski> > foldr (-) z [a,b,c,d]
21:11 <lambdabot> a - (b - (c - (d - z)))
21:12 albertus1 joined
21:12 <Cale> (we have some magic constants in lambdabot named with single letters which have various operations defined on them to build up expression strings)
21:12 <math493> Cale: Would \t -> treeCata id (\x l r -> l . r . (x:)) t [] be post-order then?
21:13 <Cale> yep
21:13 <ski> > filter (`notElem` "a") (foldr (\n c_ns c -> c_ns (c . (n :) . c)) (\c -> c []) "abcd" id)
21:13 <lambdabot> "bcbdbcb"
21:13 mojjo joined
21:13 <Cale> you'd get all the left subtree's elements, then all the right subtree's, and then the one at the root
21:13 <math493> Yeah :)
21:14 nbro joined
21:14 <math493> This is really cool stuff.
21:15 <Cale> There are a whole bunch of other things we haven't really gotten to yet, but yeah, hopefully this gives a bit of a sense of it
21:15 cdg joined
21:15 <Cale> I wanted to give some examples involving bad implementations of map and how the compiler won't let us screw it up
21:15 <Cale> Supposing we get our type signature right:
21:15 <Cale> map :: (a -> b) -> [a] -> [b]
21:16 <Cale> Let's suppose we wrote
21:16 <Cale> map f [] = []
21:16 <Cale> map f (x:xs) = x : map f xs
21:16 <ertes> @let treeTake = flip $ treeCata (const Tip) (\x ls rs n -> if n > 0 then Branch x (ls (n - 1)) (rs (n - 1)) else Tip)
21:16 <lambdabot> Defined.
21:16 <Cale> This function has a mistake in it
21:16 <Cale> We forgot to apply the function
21:16 <Cale> The compiler will detect this and complain:
21:16 jomg joined
21:16 <ertes> @let testTree2 = treeAna (\g' -> let (x, g) = randomR (0, 100000 :: Integer) g'; (gl, gr) = System.Random.split g in do guard (x /= 1); pure (x, gl, gr)) (mkStdGen 100)
21:16 <lambdabot> Defined.
21:16 <ertes> > treeTake 2 testTree2
21:16 <lambdabot> Branch 681 (Branch 78924 Tip Tip) (Branch 73332 Tip Tip)
21:17 <Cale> :t let map :: (a -> b) -> [a] -> [b]; map f [] = []; map f (x:xs) = x : map f xs in map
21:17 <lambdabot> error:
21:17 <lambdabot> • Couldn't match type ‘b1’ with ‘a1’
21:17 <lambdabot> ‘b1’ is a rigid type variable bound by
21:17 <* ski> . o O ( `treeCutDepth')
21:17 <Cale> not enough room to give us the whole error, but yeah
21:17 <math493> Cale: Hm... yeah, it's complaining at least :)
21:18 <* ski> . o O ( ".. I've got the most wonderful error message, but the margin of the channel is too small to display it" )
21:18 chlong joined
21:18 <math493> Where would I add apply to fix it?
21:18 <Cale> It can take a little practice to learn to read the error messages, but they really do tend to be helpful
21:18 <Cale> We need to apply f to x in the second case
21:18 <Cale> :t let map :: (a -> b) -> [a] -> [b]; map f [] = []; map f (x:xs) = f x : map f xs in map
21:18 <lambdabot> (a -> b) -> [a] -> [b]
21:18 <ertes> math493: fun fact: if you insist on writing 'map' in terms of 'foldr' there is exactly one way to get it right and one way to get it wrong =)
21:18 <math493> Oh, that worked :)
21:18 <Cale> What if, I dunno, we tried to apply the function twice?
21:19 <math493> ertes: Haha :D
21:19 <Cale> :t let map :: (a -> b) -> [a] -> [b]; map f [] = []; map f (x:xs) = f (f x) : map f xs in map
21:19 <lambdabot> error:
21:19 <lambdabot> • Couldn't match expected type ‘a1’ with actual type ‘b1’
21:19 <lambdabot> ‘b1’ is a rigid type variable bound by
21:19 <Cale> nope
21:19 kau joined
21:19 <Cale> because a and b would need to be the same type for that to work, and the type signature says they're allowed to be anything, in particular they might be different
21:19 <ertes> math493: so in haskell by generalising you actually improve your code correctness, because the compiler will more likely catch your mistakes
21:19 <ertes> by generalising and abstracting
21:20 <math493> :)
21:20 <math493> I really learn something today!
21:21 <math493> If I may ask a question related to the bool thing, how does this definition work? myAnd MyFalse _ = MyFalse; myAnd MyTrue x = x
21:21 <math493> I mean, what's the logic? Is myAnd basically defined by a truth table?
21:21 <ertes> math493: when two arguments come in, the two clauses are matched in order
21:21 <ski> `x' matches any argument, and gives it that name
21:21 <Cale> When we apply myAnd to some arguments, it will try to match each of the patterns in turn
21:21 <Cale> The first one to match is the winner
21:21 <ertes> myAnd MyFalse MyTrue, by the first clause, is MyFalse
21:21 <ski> `_' matches any argument, doesn't give a name to it. often called a "wildcard" or "anonymous pattern"
21:21 <Cale> So, if the first argument is MyFalse, and the second argument is anything, the result is MyFalse
21:22 wroathe joined
21:22 <ertes> myAnd MyTrue MyFalse, by the second clause, is MyFalse
21:22 <ski> ("don't care","anything goes")
21:22 <ertes> because myAnd MyTrue x = x
21:22 <ertes> for all x
21:22 Edith joined
21:22 <math493> So this says "if the first operand is false, then return false"?
21:22 <Cale> math493: A cool thing about this is that if the second argument would have been a lot of work to compute, we don't have to do that work
21:22 <ertes> whoops
21:22 <Cale> yeah
21:23 <ertes> sorry, that was non-sense
21:23 <math493> And the other part is considered an "else if" part?
21:23 <math493> myAnd MyTrue x = x
21:23 <Cale> You can think of it that way, sure
21:23 <ertes> in any case, the clauses are matched against the arguments in order, and the first match wins
21:23 <math493> So if the first one is True and the second one is False, then it's False.
21:23 <Cale> right
21:23 <math493> If the first one is True and the second one is True, then it's True.
21:23 <Cale> yep
21:24 <* ski> . o O ( annoying order dependance is annoying )
21:24 <math493> Basically, if True is the first one, then the result is defined to be equal to the second operand.
21:24 <Cale> yes
21:24 <Cale> @src (&&)
21:24 <lambdabot> True && x = x
21:24 <lambdabot> False && _ = False
21:24 <math493> Would myOr be equally simple to write using pattern matching?
21:24 <Cale> sure
21:24 <ertes> math493: try it
21:25 theorbtwo joined
21:26 chindy joined
21:26 <math493> Would this be OK?
21:26 <math493> myOr MyFalse MyFalse = MyFalse; myOr _ _ = MyTrue
21:26 <math493> > myOr MyFalse MyFalse = MyFalse; myOr _ _ = MyTrue
21:26 <lambdabot> <hint>:1:22: error:
21:26 <lambdabot> parse error on input ‘=’
21:26 <lambdabot> Perhaps you need a 'let' in a 'do' block?
21:26 <ertes> math493: it's almost fine
21:26 <math493> @let myOr MyFalse MyFalse = MyFalse; myOr _ _ = MyTrue
21:26 <lambdabot> .L.hs:195:6: error:
21:26 <lambdabot> Not in scope: data constructor ‘MyFalse’
21:26 <lambdabot> Perhaps you meant ‘False’ (imported from Data.Bool)
21:26 bhiliyam joined
21:26 <ertes> math493: it has the semantics you want, but there is one disadvantage
21:26 <Cale> oh, someone must have cleared the definitions
21:26 Rodya_ joined
21:27 <Cale> @let data MyBool = MyFalse | MyTrue deriving (Eq, Ord, Show)
21:27 <lambdabot> Defined.
21:27 <math493> Oh, then I'll just try it in my own console :)
21:27 <ertes> math493: if the first argument is True, then the result is True, independent of the second argument
21:27 <ertes> math493: ideally
21:27 <ertes> > myOr True undefined
21:27 <lambdabot> error:
21:27 <lambdabot> Variable not in scope: myOr :: Bool -> t0 -> t
21:27 <ertes> oh
21:27 <Cale> @let myOr MyFalse MyFalse = MyFalse; myOr _ _ = MyTrue
21:27 <lambdabot> Defined.
21:27 <Cale> there :)
21:27 <math493> That was what I tried to express. I wanted to say "if both are false, return false, else, return true"
21:27 <ertes> > myOr MyTrue undefined
21:27 <lambdabot> MyTrue
21:28 <ertes> oh =)
21:28 Avogadro joined
21:28 <ertes> of course
21:28 <Cale> That's actually kind of interesting
21:28 <ertes> i had a twist in my brain
21:28 <math493> But maybe I should have done it the other way :)
21:28 <Cale> I think at some point in the past, it didn't work that way :)
21:28 <Cale> possibly
21:28 <ertes> this is how i would have written it: myOr MyTrue _ = MyTrue; myOr MyFalse x = x
21:29 mtesseract joined
21:29 subttle joined
21:29 <ertes> but it's the same thing
21:29 <Cale> math493: Apparently either is fine :)
21:29 <ertes> well, i guess GHC matches the arguments in order
21:29 WarmCookie joined
21:29 <Cale> math493: ertes (and to be honest, myself as well), was expecting that since the first pattern given matched both arguments against a constructor, they would both be evaluated right away
21:29 <WarmCookie> What alternatives would be viable in a world where Haskell's parser wouldn't be whitespace sensitive?
21:30 <math493> Oh :)
21:30 <Cale> WarmCookie: semicolons and braces
21:30 <WarmCookie> I suspect the language would need additional syntax? What are the implications?
21:30 <Cale> WarmCookie: Haskell already supports semicolons and/or braces and becomes whitespace insensitive if you use them
21:30 <ski> no additional syntax
21:30 <math493> Could I also define implication and things link that?
21:30 <math493> *like
21:30 <ski> yes
21:30 <ertes> math493: now observe the coolness of your function…
21:31 <math493> ertes: Coolness how? :)
21:31 govg joined
21:31 <math493> In what sense?
21:31 <WarmCookie> Cale: ski Thanks.
21:31 <Cale> math493: Of course -- we can define any function we like on these :)
21:32 <math493> Cale: But then I'd have to check the Rosen book to find the truth table - I don't remember that one :D
21:32 <ertes> @let toMyBool False = MyFalse; toMyBool True = MyTrue
21:32 <lambdabot> Defined.
21:32 JeanCarloMachado joined
21:32 <math493> Or consult Wiki: https://en.wikipedia.org/wiki/Truth_table#Logical_implication
21:33 <math493> ertes: Is toMyBool the implication arrow? :)
21:33 <Cale> math493: Nah, it just converts ordinary Bool values to MyBool
21:33 <ertes> > foldr (\x xs -> toMyBool (even x) `myOr` xs) MyFalse (1 : [2,4..])
21:33 <lambdabot> MyTrue
21:34 <Cale> The cool part here is that we're folding over an infinite list
21:34 <Cale> > 1 : [2,4..]
21:34 <lambdabot> [1,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52...
21:34 <ertes> ah, wait
21:34 <ertes> > foldr (\x xs -> toMyBool (odd x) `myOr` xs) MyFalse (1 : [2,4..])
21:34 <lambdabot> MyTrue
21:34 <ertes> that one is more spectacular =)
21:35 <math493> Cale: Jättebra! :D
21:35 <ertes> math493: foldr (\x xs -> toMyBool (odd x) `myOr` xs) MyFalse (1 : [2,4..]) = toMyBool (odd 1) `myOr` (toMyBool (odd 2) `myOr` (toMyBool (odd 4) `myOr` …
21:35 <ertes> there is one odd number in an otherwise infinite list of even numbers
21:36 <ertes> your function short-circuits
21:36 <Cale> of course, if that one odd number isn't there, it searches forever for something it will never find
21:36 atomi joined
21:36 <math493> Hm... :D
21:36 <ertes> > foldr (\x xs -> toMyBool (odd x) `myOr` xs) MyFalse [2,4..]
21:36 <lambdabot> *Exception: stack overflow
21:36 <Cale> heh, that's worse than I imagined
21:37 <ertes> kinda odd
21:38 <ertes> @let myOr' False x = x; myOr' True _ = True
21:38 <lambdabot> Defined.
21:38 <ertes> > foldr (\x xs -> odd x `myOr'` xs) False [2,4..]
21:38 <lambdabot> mueval-core: Time limit exceeded
21:39 <ertes> @let myOr'' False False = False; myOr'' _ _ = True
21:39 <lambdabot> Defined.
21:39 binaryplease joined
21:39 <ertes> > foldr (\x xs -> odd x `myOr''` xs) False [2,4..]
21:39 <lambdabot> *Exception: stack overflow
21:39 <ertes> i think i see why it happens
21:39 <ertes> the "proper" version doesn't actually insist on pattern-matching the recursive value… it just returns it
21:39 <ertes> so it's less strict after all
21:40 <ertes> > myOr'' True undefined
21:40 <lambdabot> True
21:40 <ertes> this looks wrong
21:40 <ertes> ah, no
21:41 revprez joined
21:41 revprez_atlanta joined
21:41 govg joined
21:42 <ertes> yeah, i get it… it builds up a stack of myOr'' invocations, because it still insists on pattern-matching on the right argument to see if it's False, in which case it returns False
21:42 <ertes> the proper version doesn't actually care what the second argument is at all
21:42 <ertes> subtle difference =)
21:43 des_ joined
21:43 hexfive joined
21:46 danthemyth joined
21:47 mtesseract joined
21:47 chichou joined
21:51 freeside joined
21:54 hiratara joined
21:58 leat joined
22:00 wroathe joined
22:02 <math493> But thanks a lot, especially to Cale and ertes :)
22:02 Detrumi joined
22:03 <math493> I'm busy saving all the examples :D
22:04 gugah joined
22:04 twanvl_ joined
22:05 cables joined
22:06 wroathe joined
22:07 nick123 joined
22:09 path[l] joined
22:11 mizu_no_oto joined
22:12 wroathe joined
22:12 des_ joined
22:13 Sampuka joined
22:15 Nicmavr joined
22:18 <math493> > instance Eq MyBool where {MyTrue == MyTrue = True; MyFalse == MyFalse = True; _ == _ = False}
22:18 <lambdabot> <hint>:1:1: error: parse error on input ‘instance’
22:18 <math493> Shouldn't this work?
22:18 <ski> math493 : looks fine
22:19 <math493> ski: Hm, lambdabot is complaining
22:19 <ertes> math493: if you're trying to give that to lambdabot, instances are declarations, so you need to use @let
22:19 leat joined
22:19 <math493> Oh
22:19 <glguy> math493: That's fine, it's just not OK to define instances with '>'
22:19 <math493> @let instance Eq MyBool where {MyTrue == MyTrue = True; MyFalse == MyFalse = True; _ == _ = False}
22:19 <lambdabot> .L.hs:194:27: error:
22:19 <lambdabot> • Overlapping instances for Eq MyBool
22:19 <lambdabot> arising from the 'deriving' clause of a data type declaration
22:19 electrostat joined
22:20 <math493> Hm...
22:20 <math493> @let instance Eq2 MyBool where {MyTrue == MyTrue = True; MyFalse == MyFalse = True; _ == _ = False}
22:20 <ertes> math493: the instance is already defined
22:20 <lambdabot> .L.hs:196:10: error:
22:20 <lambdabot> Not in scope: type constructor or class ‘Eq2’
22:20 <lambdabot> Perhaps you meant one of these:
22:20 nbro joined
22:20 <math493> Why doesnt Eq2 work then?
22:20 <ski> <ertes> @let data MyBool = MyFalse | MyTrue deriving (Eq, Ord, Show)
22:20 <ski> already gave you an `Eq' instance
22:21 <ski> there is no type class named `Eq2' in scope
22:21 <math493> ski: Oh, but I thought the idea was I could create my own this way :)
22:22 <math493> But then I have to leave out Eq in deriving?
22:22 <math493> The name Eq is important?
22:22 <math493> I cannot rename it? :)
22:22 <Tuplanolla> @let class Eq2 a where (===) :: a -> a -> MyBool -- Is this what you want, math493?
22:22 <lambdabot> Defined.
22:22 <math493> I thought I could create an Eq2 instance then
22:23 <barrucadu> You can't make an Eq2 instance until an Eq2 class exists
22:23 <Tuplanolla> @let instance Eq2 MyBool where {MyTrue == MyTrue = MyTrue; MyFalse == MyFalse = MyTrue; _ == _ = MyFalse}
22:23 <math493> Tuplanolla: Well, this was just to learn, not something I needed to use for a specific purpose :)
22:23 <lambdabot> .L.hs:203:16: error: ‘==’ is not a (visible) method of class ‘Eq2’
22:23 <barrucadu> Otherwise how is GHC to know what methods the class has?
22:23 <Tuplanolla> @let instance Eq2 MyBool where {MyTrue === MyTrue = MyTrue; MyFalse === MyFalse = MyTrue; _ === _ = MyFalse}
22:23 <lambdabot> Defined.
22:23 <Tuplanolla> That's how it'd go, math493.
22:23 <math493> Thanks, Tuplanolla :)
22:25 <math493> I was basically trying to use Cale's code above - essentially, I just changed Eq to Eq2 :)
22:26 <Cale> math493: You can make your own instance of the Eq class from the Prelude, if you leave out the deriving (Eq)
22:26 suds13_ joined
22:26 <math493> Cale: Oh :)
22:26 uglyfigurine joined
22:27 <math493> Tuplanolla: Should it be == or ===? I guess three?
22:27 bhiliyam joined
22:27 Rodya_ joined
22:27 <Tuplanolla> The latter, math493. As shown, the other way is to make your own `Eq` class altogether.
22:28 <math493> OK :)
22:28 <math493> So unless I leave out Eq from deriving, then it would be:
22:28 Krymise joined
22:28 <math493> class Eq2 a where (===) :: a -> a -> MyBool
22:28 <math493> instance Eq2 MyBool where {MyTrue === MyTrue = MyTrue; MyFalse === MyFalse = MyTrue; _ === _ = MyFalse}
22:30 <math493> How can I then use Eq2, if I want to compare with Eq?
22:30 <Tuplanolla> They're completely disjoint now.
22:30 <Tuplanolla> You could however define `instance Eq a => Eq2 a` or `instance Eq2 a => Eq a` to unify the two.
22:31 <math493> Disjoint in what sense?
22:31 snowalpaca joined
22:31 <math493> They both work on MyBool, right?
22:31 <Tuplanolla> Yes, but they produce different types and have different implementations.
22:31 <math493> @let instance Eq2 a => Eq a
22:31 <lambdabot> .L.hs:194:27: error:
22:31 <lambdabot> • Overlapping instances for Eq MyBool
22:31 <lambdabot> arising from the 'deriving' clause of a data type declaration
22:31 <math493> Hm...
22:32 dsh joined
22:32 <math493> I should probably just leave out Eq from deriving then :)
22:32 <Tuplanolla> Indeed.
22:33 <math493> Tuplanolla: https://pastebin.com/mUnEGqCP
22:33 <math493> Hm...
22:33 <math493> I tried:
22:33 <math493> Prelude> data MyBool = MyFalse | MyTrue deriving (Ord, Show)
22:33 <math493> Doesn't work.
22:34 <glguy> Ord requires an Eq instance
22:34 <glguy> so if you aren't going to derive Eq, you don't get to derive Ord
22:34 <glguy> (or you need to do the deriving and instance declaration all in one unit
22:34 <math493> Oh, well... :)
22:34 j2j joined
22:35 Itkovian joined
22:35 twanvl__ joined
22:35 Unode joined
22:36 <math493> If I just do
22:36 <math493> data Bool = False | True
22:36 <math493> Should it then be possible to say
22:36 <math493> instance Eq Bool where {True == True = True; False == False = True; _ == _ = False}
22:36 <math493> Or something like this?
22:37 <math493> Here I don't derive anything
22:39 indi_ joined
22:39 Itkovian joined
22:39 <math493> But still not OK, apparently
22:39 hiratara joined
22:39 <Cale> math493: What error are you getting? That Bool is already defined?
22:40 <math493> @let instance Eq Bool where {True == True = True; False == False = True; _ == _ = False}
22:40 <lambdabot> .L.hs:207:10: error:
22:40 <lambdabot> Duplicate instance declarations:
22:40 <lambdabot> instance [safe] Eq Bool -- Defined at .L.hs:207:10
22:40 <Cale> math493: Try adding import Prelude hiding (Bool(..)) to the top of your file
22:40 <Cale> and then you can define Bool like that
22:40 <Cale> the problem is that Bool already exists and has an instance of Eq
22:40 <Cale> So you can't write another
22:40 <math493> Oh.
22:40 <math493> So Haskell has a Bool?
22:41 <Cale> yep
22:41 <math493> Hm, no...
22:41 <sophiag> has anyone here tested Haskell projects with SimGrid (http://simgrid.gforge.inria.fr/) via the FFI? they have what they describe as a "legacy interface" in C, but the primary one is in C++ and i'm not sure how difficult that is to work with, having never used the FFI before.
22:41 <Cale> It's in the Prelude, which is a module that's automatically imported unless you explicitly turn it off with import Prelude () <-- i.e. those parens contain a list of what to import
22:41 <math493> Cale: http://imgur.com/a/ynVD9
22:42 <ClaudiusMaximus> you need to import qualified Prelude as P too so you can reference P.True and P.False on the rhs of the == defn
22:42 fizbin joined
22:42 <Cale> ohh
22:42 <Cale> You're doing this at the ghci prompt
22:42 <Cale> Try putting it into a file
22:42 <Cale> and then just load that with ghci
22:42 <math493> Cale: Oh, the prompt doesn't work? :D
22:42 <Cale> The prompt is... different
22:42 <Cale> It'll accept some declarations
22:42 <math493> I'll try with a file.
22:43 <Cale> But I don't know if that import Prelude hiding will work
22:43 <Cale> oh, right
22:43 <Cale> also...
22:43 <Cale> ClaudiusMaximus has a point
22:43 <Cale> (==) always results in something which is of the *Prelude's* Bool type
22:43 <Cale> So it might just be easier if you rename your Bool somehow
22:43 <Tuplanolla> Besides it won't work as expected, because `Bool` has a special standing wrt `if` and guards.
22:44 <Cale> It should work, there's no if-expressions
22:44 <Tuplanolla> I don't remember if `RebindableSyntax` changes those two.
22:44 <Cale> I think it does
22:44 <math493> Hm, maybe it's a stupid thing to do... I just wanted to try it, but anyway... :)
22:44 hackebeilchen joined
22:44 <Cale> Try
22:44 <Cale> data B = F | T
22:45 <Cale> and then make the instance of Eq for that :)
22:45 PhatMac joined
22:45 <math493> The file didn't work either. If I only put these three lines exactly as they were written here.
22:45 <Cale> right
22:45 <math493> I can try
22:45 <Cale> You'll need import qualified Prelude as P
22:45 <Cale> and then P.True and P.False as the results of (==)
22:45 <Cale> (but not the arguments)
22:46 <math493> Prelude> data B = F | T
22:46 <math493> Prelude> instance Eq B where {T == T = T; F == F = T; _ == _ = F}
22:46 <math493> Shouldn't this be OK?
22:46 <Cale> nope
22:46 <Cale> because ...
22:46 <Cale> :t (==)
22:46 <lambdabot> Eq a => a -> a -> Bool
22:46 <math493> Oh...
22:46 <Cale> It results in a proper Prelude Bool
22:47 <Cale> If you wanted an Eq which worked with your new Bool, then you really do have to redefine the class
22:47 RoyalNightGuard joined
22:47 <Tuplanolla> This is why I briefly introduced `Eq2` earlier, math493.
22:47 <math493> OK :)
22:48 PhatMac joined
22:48 <math493> Anyway, I just wanted to try, since I thought it would be straightforward based on your example... :)
22:48 <math493> We can leave it, I think :)
22:48 <ClaudiusMaximus> note that Prelude.Eq is hardwired into some syntax too, like pattern matching of numeric and (overloaded) string literals
22:50 jao joined
22:51 allenj12 joined
22:52 Shatnerz0 joined
22:53 revprez_atlanta joined
22:54 <math493> But thanks :)
22:56 mazeinmaze_ joined
23:00 uuplusu_ joined
23:01 <sveit> is there a function like scanl that also gives you the tail of the list? maybe i should be using a different abstraction? here is an example implementation that does what I want on lists: (\f a xs -> zip (scanl f a xs) (zipWith (flip const) (undefined:xs) $ iterate tail xs))
23:01 <Cale> sveit: scanl over tails xs?
23:02 <Cale> :t tails
23:02 <lambdabot> [a] -> [[a]]
23:02 thebored joined
23:02 dmead joined
23:06 <sveit> ok, so i implemented tails xs = (zipWith (flip const) (undefined:xs) $ iterate tail xs), which means i can now write my original function as (\f a xs -> zip (scanl f a xs) $ tails xs). is this what you meant?
23:06 boob joined
23:07 hexfive joined
23:07 <dmead> ?yow
23:07 <lambdabot> I've got a COUSIN who works in the GARMENT DISTRICT ...
23:08 rootme joined
23:08 <sveit> or (simpler?) (\f a -> zip <$> scanl f a <*> tails). can this be made more idiomatic/efficient?
23:08 nick123 joined
23:09 ozgura joined
23:09 <ClaudiusMaximus> i'd say that r-> usage is a bit confusing, at first glance i had to double-check which applicative instance it was using (i thought it might be [] which would do something completely different)
23:09 rootme left
23:10 <ClaudiusMaximus> sveit: import Data.List (tails) is probably better than defining it youself
23:10 mizu_no_oto_work joined
23:11 markus1209 joined
23:11 markus1219 joined
23:11 aglorei joined
23:13 <sveit> thanks. incidentally, if i were defining tails, is tails xs = zipWith (flip const) (undefined:xs) $ iterate tail xs a reasonable way to do it? I can see it is defined in terms of the build machinery in base, but this definition should fuse well as well since it's just using zipWith, right?
23:13 <orion> :hello
23:13 <orion> Hmm, I guess that command is disabled.
23:14 theDon_ joined
23:14 uglyfigurine joined
23:14 aglorei joined
23:17 <c_wraith> sveit, zipWith doesn't actually fuse on the consumption side. though tails probably doesn't either.
23:18 <sveit> why doesn't zipWith fuse?
23:18 <c_wraith> the current fusion framework doesn't handle two lists as input at the same time.
23:19 eacameron joined
23:20 tauli joined
23:20 <c_wraith> it's been shown basing fusion on hyperfunctions can do that, but that isn't something that's been adopted into the libraries.
23:21 path[l] joined
23:22 <sveit> so this means that when any part of the zipWith is forced, it actually allocates the whole spine?
23:23 <c_wraith> no..
23:23 <c_wraith> it's still lazy.
23:24 ziarkaen joined
23:24 <c_wraith> it just means that (:) constructors on its input lists will be allocated and pattern-matched
23:24 <c_wraith> fusion eliminates that.
23:25 bjz joined
23:26 orbifx joined
23:27 leat joined
23:28 bhiliyam joined
23:28 Eduard_Munteanu joined
23:29 Rodya_ joined
23:30 hackebeilchen joined
23:32 pwnz0r joined
23:34 zero_byte joined
23:34 path[l] joined
23:34 robertkennedy joined
23:37 revprez_atlanta joined
23:42 Itkovian joined
23:43 path[l] joined
23:44 coot joined
23:47 meba joined
23:47 rotaerk joined
23:48 nakal_ joined
23:48 holla joined
23:48 orbifx joined
23:49 xiinotulp joined
23:53 YongJoon joined
23:55 holla joined
23:59 dfordivam joined