<    March 2017    >
Su Mo Tu We Th Fr Sa  
          1  2  3  4  
 5  6  7  8  9 10 11  
12 13 14 15 16 17 18  
19 20 21 22 23 24 25  
26 27 28 29 30 31
00:01 leothrix joined
00:02 <mounty> When you run Haddock on TH source, it warns about lack of documentation for TH-inserted symbols. It's a bit hard to document these. Is it possible to tell Haddock to suppress the warning for these symbols?
00:03 <glguy> mounty: No, but if your TH can be configured not to generate type signatures, you can write them yourself and attach documentation to them
00:05 <mounty> glguy: I don't have control of the TH; it's mainly Yesod stuff.
00:34 <mounty> glguy: oh wait; ISWYM ... but no, that would be fiddly; I'll just live with it.
00:39 vaibhavsagar joined
00:40 louispan joined
00:49 ExpHP_ joined
00:52 Rodya_ joined
00:58 <mounty> glguy: there is https://www.haskell.org/haddock/doc/html/module-attributes.html -- {-# OPTIONS_HADDOCK prune #-}
00:58 mac10688 joined
01:07 dni- joined
01:07 <mounty> Then it seems that Haddock doesn't have the same information that ghc does because it doesn't find some symbols imported from libraries; e.g., import Database.HDBC.PostgreSQL (Connection)
01:09 louispan joined
01:27 animated joined
01:33 harfangk joined
01:41 \Mike joined
01:44 hphuoc25 joined
01:48 Mikan joined
01:49 Guest80799 joined
01:49 Guest80799 joined
01:53 eacameron joined
01:55 Rodya_ joined
02:00 exferenceBot joined
02:08 andyhoang joined
02:10 patbecich joined
02:12 louispan joined
02:15 nomotif joined
02:20 exferenceBot joined
02:25 hexagoxel joined
02:26 Rodya_ joined
02:36 approaching236 joined
02:44 argent0 joined
02:44 <mac10688> Is there a better way to create a Data.Map besides starting starting with an empty map or singleton and adding lookup value? I was expecting a function that takes an array of some data structure and makes a map out of it
02:44 approaching236 joined
02:44 <mac10688> I guess I'll just use a foldl
02:46 <MarcelineVQ> I'd be inclined to use fromList
02:47 <mac10688> yeah! lol that's what I was looking for! I started reading examples of other functions and saw it all over the place. I'm surprised I didn't see it listed on the constructors section
02:47 <MarcelineVQ> yes it's hidden away in the Lists section
02:48 <mac10688> ah ok. thanks
02:49 <MarcelineVQ> you'll also see it if you 'show' a Map
02:50 <MarcelineVQ> with the idea that fromList [(5,"a"), (3,"b"), (5, "c")] is a valid form to show a map since typing that in ghci gets you a Map
02:56 dni- joined
02:57 <mac10688> ah
03:02 <mac10688> seems kind of odd that I have to add containers to the cabal file. Maps is basic to most programming languages. I think I said this before. It just makes me scratch my head
03:04 splanch joined
03:05 ode joined
03:05 <ExpHP> my latest project has 30 things in its build depends barely a week in
03:07 aarvar joined
03:08 <mac10688> yikes lol
03:08 <mac10688> I was looking at ghcjs and saw all the imports and I said no thanks
03:13 conal joined
03:25 hphuoc25 joined
03:25 eacameron joined
03:30 asivitz joined
03:36 mounty joined
03:51 louispan joined
03:55 splanch joined
03:55 <kadoban> mac10688: Hmm? GHCJS is a compiler, who cares how many imports it has?
04:02 Rodya_ joined
04:04 <mac10688> kadoban, I must have misunderstood something. I was looking at an example of how to use it. Like a hello world
04:05 <mac10688> https://github.com/ghcjs/ghcjs-examples/blob/master/ghcjs-hello/src/Main.hs
04:06 <kadoban> Ahh
04:06 eacameron joined
04:07 <kadoban> That is quite a decent amount of includes.
04:14 argent0 joined
04:28 ExpHP joined
04:32 andyhoang joined
04:38 geekosaur joined
04:39 Sose joined
04:45 dni- joined
04:45 sypwex joined
04:56 yellowj joined
04:59 dni- joined
05:00 splanch joined
05:04 Rodya_ joined
05:06 geekosaur joined
05:08 bungoman joined
05:17 louispan joined
05:21 splanch joined
05:23 meandi_2 joined
05:25 Durz0 joined
05:30 hphuoc25 joined
05:38 malaclyps joined
05:39 uglyfigurine joined
05:45 ali_bush joined
05:47 andyhoang joined
05:59 kritzcreek_ joined
06:03 hphuoc25 joined
06:03 hphuoc25 joined
06:04 Gurkenglas_ joined
06:05 Rodya_ joined
06:05 eacameron joined
06:22 Ferdirand joined
06:28 eacameron joined
06:29 hphuoc25 joined
06:31 hphuoc25 joined
06:41 eacameron joined
06:49 sypwex joined
06:52 Denthir joined
06:58 xificurC joined
07:05 Denthir joined
07:06 louispan joined
07:12 simdevs joined
07:12 raduom joined
07:13 simdevs left
07:22 galderz joined
07:27 thc202 joined
07:30 patbecich joined
07:30 <xificurC> Akii: hello if you're there. I've pushed the project yesterday to gitlab and just tried to run `stack test` on my work computer with the same error as yesterday
07:31 <Akii> xificurC: yup, could reproduce that yesterday
07:32 <Akii> xificurC: got it! :D
07:32 <Akii> that's a weird one but the `Spec.h` file must not have a module declaration
07:32 <Akii> just delete the first line, afterwards it works
07:33 <Akii> any other modules you create in test/ can have a module name again
07:33 <Akii> just not the main one
07:33 <xificurC> -_-
07:33 <xificurC> that's a weird condition, and the error message helps 0%. Funny since the error messages are usually so good
07:34 <Akii> yup
07:35 <Akii> took me a while to figure out when I first ran into it
07:35 <Akii> but that's about the worst I've gotten so far
07:35 <Akii> well, I'm now looking into lenses and pipes; the type errors will become interesting :D
07:36 <xificurC> Akii: if I put the tests in another file (IntroSpec.hs) and import it in Spec.hs `stack test` says I should add IntroSpec to exposed- of other-modules. Which and why
07:36 <Akii> add IntroSpec to other-modules in the cabal file
07:36 <Akii> why? I don't know
07:37 <xificurC> alright
07:37 <xificurC> thanks for your help
07:37 <Akii> np :D
07:37 mattyw joined
07:39 eacameron joined
07:40 patbecich joined
07:44 eacameron joined
07:52 nil_ joined
07:52 pie_ joined
07:54 Levex joined
08:01 for{} joined
08:01 <for{}> hi
08:02 <for{}> why when we define a lambda function, we use -> instead of =?
08:04 <nil_> for{}: good question. I don't think it really means anything, it's probably just to make parsing easier (you don't need to figure out which '=' belongs where if you've got a lambda inside a definition).
08:05 <nil_> But I don't see anything wrong with let square = \x = x*x either.
08:07 Rodya_ joined
08:07 <jle`> re: syntax decisions, i think there was a rule when they were designing haskell that the first suggestion would be accepted without discussion
08:07 <jle`> becuase they didn't want to get hung up on syntax and instead focus on the actual language
08:07 <jle`> so a lot of decisions in haskell syntax is sort of just because it was the first idea
08:07 <jle`> and there wasn't *too* much deep thought put into it
08:08 <nil_> I'm fairly sure that's not how it happened. The designers paid a lot of attention to clean syntax.
08:09 colt44 joined
08:09 raduom joined
08:09 <nil_> There's a paragraph in "A History of Haskell:
08:09 <nil_> Being Lazy With Class" titled "Syntax matters".
08:09 <jle`> ah hm, it looks like i misrecalled. thanks
08:10 <jle`> looking at that, i think i was referring to the part where they mentioned that someone was in charge of cutting syntax debates short
08:10 <nil_> Oh.
08:10 <jle`> but it's definitely not as extreme as 'what's the first thing lol'
08:10 <nil_> That's more like JavaScript.
08:11 <jle`> hah
08:11 <jle`> developed in 10 days, and now haunting us for all eternity
08:12 <jle`> fwiw idris uses => for lambdas
08:13 sypwex joined
08:13 nacon joined
08:13 <jle`> scala too
08:14 <nil_> It's kind of surprising no one went for either '=' or '.'
08:15 <jle`> coffee script uses ->
08:16 <jle`> . makes the most mathematical sense... but i think = is already taken for assignment/declaration syntax
08:16 <jle`> since the -> in lambda isn't quite assignment/declaration
08:16 <nil_> for{}: it seems to be pretty arbitrary. Don't worry too much about it!
08:16 <jle`> "=" in haskell always refers to a declaration/definition
08:17 <nil_> jle`: in a way a lambda expression /is/ a definition, so I don't see a problem.
08:17 <nil_> "This function that I'm defining /is/ ..."
08:17 <jle`> (\x -> x + 3), what is being defined/declared?
08:17 <jle`> just the expression itself
08:17 <nil_> "The anonymous function I'm defining" is being defined.
08:18 <jle`> the anonymous function is the (\x -> x + 3)
08:18 <nil_> Right
08:18 <jle`> it's not the 'x'
08:18 <jle`> or the 'x + 3'
08:18 <jle`> so it wouldn't be too consistent to have (\x = x + 3)
08:18 Sose joined
08:18 zero_byte joined
08:18 <nil_> You've got the lambda symbol there, so it's perfectly reasonable to see it as a definition:
08:18 <nil_> λx = x*x
08:19 <jle`> are you defining (\x) to be (x*x) ?
08:19 <nil_> "The anonymous function that takes x _is_ x*x"
08:19 <nil_> Yep
08:20 <jle`> but, (\x -> ...) is the anonymous function that takes x. the anonymous function that takes x _is_ (\x -> ...)
08:20 <jle`> x*x isn't an anonymous function
08:20 <nil_> Well, you could interpret let f x = x*x the same way, no?
08:21 <nil_> If you get philosophical about it, f x *isn't* (x*x).
08:21 <jle`> well, the two are equivalent
08:21 DataComputist joined
08:21 <jle`> referential transparency and all
08:22 <nil_> You get that with a lambda too, what you don't get is the name and that's it.
08:22 rlpowell joined
08:22 mattyw joined
08:22 <jle`> i mean, everywhere you write 'f x', it's equivalent to writing 'x*x'
08:23 <jle`> f x *is* x*x. but `\x` isn't `x*x`
08:23 <nil_> I get it. You can't do that with a lambda, but the reason is the lack of a name.
08:23 vaibhavsagar joined
08:24 grdryn joined
08:24 <nil_> Right. I see where you're coming from, I'm just saying the point is the lambda being anonymous is the only thing that sets it apart from a regular definition.
08:24 <jle`> i should have clarified then; = in haskell refers to defining a name
08:24 <jle`> it's with definitions
08:24 <nil_> Oh, that sounds very right then.
08:25 <jle`> not that it's too important in the end :)
08:25 splanch joined
08:26 merijn joined
08:38 <nil_> System F extends the STLC with polymorphic types such as forall a. a -> [a] right?
08:39 <nil_> What does System FC to extend System F?
08:40 sypwex joined
08:40 <merijn> nil_: Sounds like you want to read up on the lambda cube!
08:40 <nil_> Didn't find System FC there. :(
08:41 <merijn> hmm, isn't it in there? I keep confusing things
08:41 patbecich joined
08:41 <nil_> An easy thing to be sure.
08:42 <merijn> ah, so System FC is just System F with coercions and constraints, afaict
08:46 <nil_> constraints =?= typeclasses
08:47 alexelcu joined
08:47 alexelcu left
08:48 alexelcu joined
08:49 <geekosaur> typeclasses and equality constraints (a ~ Foo)
08:50 <merijn> Typeclasses are enforced by constraint in GHC, but there's no reason constraints would be restricted to typeclasses
08:50 <merijn> nil_: You could have a "list is shorter than X elements" constraint! https://gist.github.com/merijn/39dc86e345e87276c523
08:51 <nil_> Wow...
08:52 <nil_> () is like "True in constraintland", right?
08:52 <nil_> Am I supposed to think "types as propositions" when I see that?
08:52 <jle`> be aware that that's not the same () as Unit
08:52 <jle`> that's (), the empty constraint
08:52 <nil_> It's notM
08:52 <nil_> Oh
08:53 <jle`> foo :: (Bar a, Baz c) => ...
08:53 <jle`> foo :: (Bar a) => ...
08:53 <jle`> foo :: () => ...
08:53 <jle`> etc.
08:53 <merijn> nil_: () is the "trivial" constraint, yes
08:53 <merijn> nil_: i.e. the constraint the always works :)
08:53 <jle`> the identity in the monoid of constraints
08:53 <nil_> Huh
08:53 <jle`> s/the/a
08:54 <merijn> nil_: I have a couple of other neat standalone example of type level abuse I wrote for people to try and understand :)
08:55 <merijn> https://gist.github.com/merijn/6130082 <- I'm proud of this clever abuse of constraints :)
08:55 <merijn> Similar use of failing constraints here: https://gist.github.com/merijn/dc00bc7cebd6df012c5e
08:56 <nil_> What's (':)? Strict consing?
08:57 Denthir joined
08:58 <jle`> are you familiar with data kinds?
08:58 <jle`> it's the cons for a type-level list
08:58 gregman_ joined
08:58 <merijn> nil_: Type level cons
08:58 <nil_> ._.
08:59 <nil_> brb after the standup.
08:59 <jle`> :k '[Int, Bool, String]
08:59 <lambdabot> [*]
08:59 <jle`> :k Int ': Bool ': String ': '[]
08:59 <lambdabot> [*]
09:06 slomo joined
09:07 <nil_> What is that exactly?
09:10 colt44 joined
09:10 eacameron joined
09:15 sypwex joined
09:16 uglyfigurine joined
09:18 andyhoang joined
09:20 <nil_> Oh, it's a list /of types/, isn't it?
09:21 <merijn> nil_: Right
09:22 <merijn> (A bit busy for in-depth explanation)
09:22 <nil_> :) That's cool
09:22 <merijn> nil_: But yes, it's a type-level list of types which tracks the type of every element in the list
09:23 <merijn> And, whether the list is empty or not, for example, check the implementation of head and tail :)
09:23 <merijn> You can tell from the types you can't actually do "head" on the empty HList :)
09:30 galderz joined
09:35 <nil_> I think I figured it out, really clever.
09:35 <nil_> Do I ever actually want to do this?
09:36 <merijn> nil_: Yes, no, maybe :)
09:36 <merijn> nil_: I mostly wrote these to see if I could and to understand the relevant extensions better
09:36 azahi joined
09:36 Pupnik joined
09:37 <merijn> nil_: Actually, you probably DO want to do this, but if you find yourself really needing it, you might want to use something other than Haskell :)
09:37 <merijn> nil_: Idris (for example) makes this kinda thing much easier
09:37 louispan joined
09:37 <nil_> So what you built is a kind of limited dependent typing?
09:38 <merijn> nil_: It's not quite dependent yet, but for example the LessThan constraint one would be much nicer using dependent types
09:39 <merijn> nil_: To get the 3rd index of a list you end up writing
09:39 <merijn> index myList (ISucc (ISucc (ISucc IZero)))
09:39 <merijn> Why? because you need to construct an "Index n" with the right 'n'
09:40 <merijn> With dependent types you could simply write "index myList 5" and use the '5' directly in the type of index
09:40 <nil_> Interesting.
09:41 <merijn> nil_: There's a nice example of type safe printf in Idris showing this
09:42 patbecich joined
09:48 <__rgn> hi merijn. i made some progress with <*> problem if you remember.
09:49 <__rgn> the key realization was that the type variables can be used to infer how the values get passed around, like you said i think
09:50 <merijn> __rgn: Well, if it's not what I said, it's definitely what I intended to say ;)
09:50 <__rgn> (<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
09:51 <__rgn> like the `a` of second argument is passed to the first function
09:51 <merijn> __rgn: Right :)
09:52 <merijn> __rgn: Because there's no other way you could ever get a 'b' :)
09:53 <__rgn> i thought they represent types only, not that there was consistency like that
09:53 <__rgn> also, using a simpler example like (+) <*> (+2) helped a bit
09:55 <merijn> __rgn: Well, they do represent types only, but that can often tell you a lot, since variables with the same names must be the same, which lets you make conclusion like this (the result of the 2nd argument being passed to the first) :)
09:56 <__rgn> right..
09:58 takle joined
10:01 takle joined
10:02 eacameron joined
10:06 eacameron joined
10:06 yellowj joined
10:07 <__rgn> so you can legitimately use the type variables to infer if they are the same values in reality
10:07 <__rgn> sometimes, at least
10:08 <__rgn> :t (<*>) :: (a -> a -> a) -> (a -> a) -> (a -> a)
10:08 <lambdabot> (a -> a -> a) -> (a -> a) -> a -> a
10:08 Rodya_ joined
10:12 splanch joined
10:13 nokomo joined
10:13 nokomo left
10:31 eacameron joined
10:34 aarvar joined
10:40 <merijn> __rgn: Well, you can't infer if they are the same value in general
10:41 <merijn> __rgn: But in this specific case you can see that there's no 'a' that's passed as argument, but an 'a' must be used (otherwise the function could only do "undefined"), so here you can infer that
10:41 <merijn> __rgn: Basically, we know that it's impossible to create an 'a' out of thin air
10:44 patbecich joined
10:54 <__rgn> hm
10:56 <merijn> Well, not entirely, there is:
10:56 <merijn> :t undefined
10:56 <lambdabot> a
10:57 <merijn> But the only 'a' we can ever create out of thin air is, basically, bottom (i.e. crashing/infinite computation), so we can pretend it doesn't exist :)
10:57 DataComputist joined
10:58 mengu joined
10:59 <__rgn> am i supposed to intuit some kind of relationship between
10:59 <__rgn> Just (+1) <*> Just 1
10:59 <__rgn> and (+) <*> (+1)
11:00 <__rgn> i picked Maybe arbitrarily
11:01 stef204 joined
11:01 <merijn> __rgn: Well, not anything much deeper than "both happen to be Applicative" :)
11:02 <merijn> __rgn: A reasonable intution of Applicative is: "fmap, generalised to functions of any arity" :)
11:03 <merijn> fmap can apply a function inside a Functor, but only to one argument
11:03 <merijn> :t fmap (+) Nothing
11:03 <lambdabot> Num a => Maybe (a -> a)
11:04 <merijn> Now we have a Maybe with a function inside, but how do you get that function "out" to apply to something else? For Maybe specifically you can use pattern matching, but if you don't know what the functor is...
11:04 <merijn> :t fmap (+)
11:04 <lambdabot> (Num a, Functor f) => f a -> f (a -> a)
11:04 <merijn> We have 'f (a -> a)', but since we don't know what 'f' is, it's not possible to actually get the 'a -> a' "out" to apply it to something else
11:05 <merijn> However, if we use Applicative then we *can* do that, using <*>
11:05 splanch joined
11:07 <__rgn> i can make sense out of applicative in context of boxy types. apply a function inside a container to value in a container of the same type
11:07 AndreasK joined
11:07 <__rgn> but i see no resemblance of that with (-> r) thing
11:08 <merijn> __rgn: That's usually the downside of thinking of "boxy" types :)
11:09 Rodya_ joined
11:09 <merijn> __rgn: Well, '(->) r' is kinda like having an infinite (well, 1 per possible value of 'r') number of boxes, and getting the function out of that one. But we don't have to pick which one until the end
11:09 <merijn> __rgn: Honestly, I would recommend not thinking too much about the "why", because there's many things that don't have a good intuitive "why"
11:10 <merijn> __rgn: Instead, focus on "what are the laws?" and "can I figure out why the laws are valid?"
11:10 <merijn> __rgn: Are you familiar with Typeclassopedia?
11:11 <__rgn> i remember using it
11:19 mattyw joined
11:20 <__rgn> it talks about functor as a container
11:21 <merijn> Unfortunate, but oh well :)
11:22 Denthir joined
11:22 netheranthem joined
11:23 Prutheus joined
11:26 jle` joined
11:28 DataComputist joined
11:38 <nil_> " Another intuition is that a
11:38 <nil_> Functor
11:38 <nil_> represents some sort of “computational
11:38 <nil_> context.” "
11:38 <nil_> (Sorry, weird pdf encoding.)
11:41 DataComputist joined
11:42 sypwex joined
11:44 louispan joined
11:45 andyhoang joined
11:45 patbecich joined
11:47 sigmundv joined
11:50 <__rgn> i've heard that one before, in context of monad
11:59 Levex joined
12:01 eacameron joined
12:05 Denthir joined
12:10 Rodya_ joined
12:15 hellofunk joined
12:26 eacameron joined
12:31 Zialus joined
12:40 sunflower_ joined
12:40 <sunflower_> hi
12:41 chlong joined
12:41 <sunflower_> how can i subtract from every element of a list like [1..6] 7 in order to get a new list, using map?
12:42 <tuturto> you need a function that subtracts 7
12:42 <sunflower_> i tried `map ((-)7) [1..6]` but i dont get what i want
12:42 <sunflower_> > map ((-)7) [1..6]
12:42 <lambdabot> [6,5,4,3,2,1]
12:43 <sunflower_> i want -6,-5...
12:43 <nil_> Unfortunately ((-)7) parses as negative 7.
12:44 <sunflower_> > map (-7) [1..6]
12:44 <lambdabot> error:
12:44 <lambdabot> • Could not deduce (Enum a0)
12:44 <lambdabot> from the context: (Enum a, Num (a -> b), Num a)
12:44 ederign joined
12:44 <nil_> You can try using a lambda if you're familiar with lambdas. There's also a function called subtract that does the same thing as (-).
12:45 <sunflower_> ok, so lambda or subtract are the right tools?
12:46 <nil_> I guess you can even do it with (-) if you want. I just realized what I first wrote isn't true. :)
12:46 <nil_> ((-)7) is *not* negative 7.
12:47 <nil_> Look at what you got when you tried that! What's going on there?
12:47 patbecich joined
12:47 mojjo joined
12:47 <sunflower_> i wrote two commands
12:48 <nil_> Yeah, I mean the one that worked, sort of.
12:48 <nil_> The first one.
12:49 <sunflower_> i saw it subtracts each element of the list from 7
12:51 <sunflower_> i dont understand why (-) isnt subtract
12:51 azahi joined
12:51 <sunflower_> they seem to have the same signature
12:52 <nil_> Exactly, so how can they be different?
12:53 dni- joined
12:53 <sunflower_> subtract does subtracts from each element 7 while (-) does the reverse
12:53 <nil_> > (-) 7 2
12:53 <lambdabot> 5
12:53 <nil_> > subtract 7 2
12:53 <lambdabot> -5
12:54 <Akii> > 7 `subtract` 2
12:54 <lambdabot> -5
12:54 <nil_> Now you can write your function easily!
12:54 <Akii> (what did I even expect to happen..)
12:54 <sunflower_> i just hoogled and it seems subtract is flip (-)
12:54 <merijn> sunflower_: Right
12:55 <merijn> sunflower_: The problem is that you can write "(+5)" to partially apply +
12:55 <merijn> sunflower_: but writing (-5) gets interpreted as negative 5
12:55 <sunflower_> thats why i wrote ((-)5)
12:55 <merijn> sunflower_: ((-)5) == (5-)
12:56 <merijn> (+) 2 3 = 2 + 3
12:56 <merijn> So '(+) 2' is (2+)
12:56 <sunflower_> but subtraction isnt commutative
12:56 <merijn> Now, for + there is no difference between x + y and y + x, so (+5) and ((+)5) end up doing the same
12:56 <merijn> sunflower_: Right
12:57 <sunflower_> thanks
12:57 <nil_> That's the point. :)
13:14 ThomasLocke joined
13:19 mattyw joined
13:21 uglyfigurine joined
13:22 uglyfigurine joined
13:23 cur8or joined
13:25 snowcrshd joined
13:27 mizu_no_oto_work joined
13:32 andyhoang joined
13:36 <__rgn> does fmap id = id mean for example fmap id [1] == id [1]
13:37 <__rgn> or is that law to be interpreted in some other sense
13:37 <qmm> > map (1-) [1,2,3,4]
13:37 <lambdabot> [0,-1,-2,-3]
13:37 <qmm> i don't know what's going on here
13:38 <sshine> > map (\x -> 1-x) [1,2,3,4]
13:38 <qmm> 1 - 1 = 0, understood. 2 - 1 = 1
13:38 <lambdabot> [0,-1,-2,-3]
13:38 <qmm> oh
13:38 <qmm> duh :)
13:38 <qmm> thanks sshine
13:38 <qmm> i should go back to bed :)
13:38 <sshine> map (1:) [[], [2], [2,3], [2,3,4]]
13:38 <sshine> > map (1:) [[], [2], [2,3], [2,3,4]]
13:38 <lambdabot> [[1],[1,2],[1,2,3],[1,2,3,4]]
13:39 <sshine> > map (++"man!") ["Bat", "Wat"]
13:39 <lambdabot> ["Batman!","Watman!"]
13:39 <Cale> __rgn: No, that's right.
13:39 <merijn> __rgn: What it means that "fmap id x == id x" (and thus "fmap id x == x")
13:39 <Cale> __rgn: Two functions are equal if they produce the same result for every possible argument
13:40 <merijn> Cale: s/equal/extensionally equal/ ;)
13:40 <__rgn> okay i see, the law ensures that structure doesn't change
13:41 nil_ joined
13:41 harfangk joined
13:42 <Cale> Well, that's the kind of equality we're talking about with this law here :)
13:42 pbrant joined
13:46 splanch joined
13:48 patbecich joined
13:57 <parsnip> went on gumroad to check but, we're still on 0.12.0, right?
13:57 <parsnip> *with haskellBook
13:59 stef204 joined
14:00 albertus1 joined
14:10 vmeson joined
14:11 tdfirth joined
14:11 Rodya_ joined
14:11 jathan joined
14:11 <nil_> Nomenclature question: was there a compelling reason to make the keyword "typeclass" instead of the more obvious "interface"?
14:14 Rodya_ joined
14:28 eacameron joined
14:31 WarmCookie joined
14:31 carlomagno joined
14:37 <Cale> nil_: I dunno, type classes are literally classes of types.
14:38 <Cale> Though I suppose as soon as they got generalised to multiple parameters, that interpretation became less clear.
14:38 <nil_> They're also literally interfaces.
14:38 <Cale> type relation might have been a better name, if we started from there
14:38 <Cale> (A class being another word for a unary relation)
14:39 Rodya_ joined
14:39 <nil_> Unary? I don't follow.
14:40 <Cale> Well, type classes are thought of as properties that types might satisfy.
14:41 <Cale> In the case that they have multiple parameters, they become more arbitrary relations between types
14:42 <Cale> In the case that there's just one parameter (i.e. it's a unary relation), there's also the interpretation that it's a set, or class, of types.
14:45 <nil_> Okay, got it. Is there anything wrong with "interface" though?
14:45 <Cale> Not particularly
14:46 <Cale> I mean, you can also look at it from the perspective of what they do with terms, rather than what they do with types, and then "interface" makes more sense.
14:51 mengu joined
14:58 earldouglas joined
15:07 DataComputist joined
15:07 <nil_> Another naming question: what does one call a homomorphism mapping an object A to itself?
15:09 <nil_> My brain keeps whispering "auto-homomorphism" to me.
15:12 <WarmCookie> Whether the morphisms are homomorphic or not, I believe if it's from object A to itself, what you're describing is just identity.
15:14 splanch joined
15:15 patbecich joined
15:18 <nil_> No, it's not. A thing can be homomorphic to itself in non-trivial ways.
15:21 nick_h joined
15:21 <nil_> Like I'm pretty sure all groups are homomorphic to themselves due to inverses.
15:24 <hrnz> G → G, g ↦ g^{-1} is an isomorphism iff G is abelian
15:26 <__rgn> how can i learn signature of <*> in context of tuple like (1, 2)?
15:27 <nil_> hrnz: nice, thank you!
15:28 <nil_> hrnz: is there a name for "homomorphism to itself" though?
15:28 <ski> endomorphism
15:28 <hrnz> endomorphism
15:28 <nil_> Oh.
15:28 <nil_> Cool, thanks. :)
15:29 <hrnz> there's also automorphism for both endomorphism and isomorphism :)
15:29 <ski> __rgn : are you talking about `instance Monoid w => Applicative (w,)' ?
15:29 <__rgn> maybe
15:30 <__rgn> applying my previous knowledge, i tried (succ) <*> (1)
15:30 <nil_> You don't really need a Monoid for that.
15:32 <nil_> Uh, there's a language extension called "TypeApplications" that might give you what you're after.
15:33 <__rgn> how's that?
15:33 <nil_> It can show you the type of a function specialized to a certain typeclass instance.
15:34 <nil_> Wait, it's not "TypeApplications" after all... Guys, what's that extension called?
15:34 nick_h joined
15:34 <WarmCookie> It is TypeApplications.
15:35 <ski> nil_ : for `(w,f) <*> (w0,a) = (...,f a)', you need to combine `w' and `w0'
15:35 <ski> also, for `pure a = (...,a)', you need a "default" value to use
15:35 <nil_> ski: sure, but that's not what __rgn is trying to do, is it?
15:35 <ski> and the applicative laws then imply that this needs to be a monoid
15:35 <ski> nil_ : i don't know yet
15:36 <nil_> ski: when I said Monoid isn't necessary, I was just looking at (succ) <*> (1).
15:36 <* ski> isn't sure what __rgn intended by that
15:37 <WarmCookie> __rgn: <*> :: Applicative f => f (a -> b) -> f a -> f b
15:37 <WarmCookie> __rgn: <*> :: (Num f, Applicative (f,)) => (f,) (a -> b) -> (f,) a -> (f,) b
15:37 <WarmCookie> __rgn: <*> :: Num f => (f, a -> b) -> (f, a) -> (f, b)
15:37 <WarmCookie> Did I do this right?
15:38 <WarmCookie> > (0, succ) <*> (0, 42)
15:38 <lambdabot> error:
15:38 <lambdabot> • Ambiguous type variable ‘t0’ arising from a use of ‘show_M709251288765...
15:38 <lambdabot> prevents the constraint ‘(Show t0)’ from being solved.
15:38 <ski> `succ' doesn't have a type matching `(f,a -> b)'
15:39 rstefanic joined
15:39 <* nil_> thinks __rgn is looking for the Identity Applicative.
15:40 <nil_> > Identity succ <*> Identity 1
15:40 <lambdabot> Identity 2
15:41 <WarmCookie> I believe it has to be "in the context of tuple like (1, 2)" from the original statement.
15:41 <__rgn> [(*2), succ] <*> [1]
15:41 <WarmCookie> I'm lost though.
15:41 <__rgn> i'm trying to do this but instead tuple as result
15:42 <monochrom> No, tuple and [] are unrelated.
15:42 <nil_> Well, tuples don't exactly work like lists. What you just typed is the correct solution.
15:42 <monochrom> Instead, Maybe and [] are closer.
15:43 alexelcu joined
15:52 <__rgn> alright. thanks
15:53 azahi joined
15:54 eacameron joined
16:04 earldouglas joined
16:13 des_ joined
16:16 michbad joined
16:17 patbecich joined
16:22 expo873 joined
16:26 wildlander joined
16:28 mac10688 joined
16:34 <__rgn> > (,) <$> succ <*> (*2) $ 1
16:34 <lambdabot> (2,2)
16:37 <ski> that's using `Applicative (rho ->)' (in this case `rho = Integer')
16:39 animated joined
16:42 delexi joined
16:44 systemfault joined
16:53 mengu joined
16:54 Denthir joined
16:57 argent0 joined
16:58 albertus1 joined
17:06 davs joined
17:16 <__rgn> what is rho?
17:19 <ski> just a type variable, meaning any type could go there
17:19 <ski> (in this case `Integer')
17:19 jud joined
17:19 <des_> I am getting non-type variable argument in the constraint, and I can't figure out why.
17:20 test joined
17:20 <des_> numbers [] = 0
17:20 <des_> numbers (x:xs) = (*) . (10^) (length xs) x + numbers xs
17:20 patbecich joined
17:20 <glguy> des_: try writing it without wedging in the . operator
17:20 <ski> or maybe add more brackets
17:21 <ski> (it's not clear what `numbers' is supposed to do)
17:21 <glguy> It's trying to turn [1,2,3] into 123
17:22 <ski> oh
17:22 <* ski> . o O ( attribute grammars )
17:24 <glguy> 10^(length xs) * x + numbers xs -- or -- ((*) . (10^)) (length xs) x + numbers xs
17:24 <glguy> 10^length xs * x + numbers xs -- or -- ((*) . (10^)) (length xs) x + numbers xs
17:28 mengu joined
17:29 <des_> OK, thank you that worked. Geese, I was stuck on that too long.
17:32 <ski> > let fromBase :: forall a. Num a => a -> [a] -> a; fromBase b ds = n where (l,n) = lengthAndFromBase ds; lengthAndFromBase :: [a] -> (Int,a); lengthAndFromBase [] = (0,0); lengthAndFromBase (d:ds) = (l + 1,10^l * d + n) where (l,n) = lengthAndFromBase ds in fromBase 10 [1,2,3]
17:32 <lambdabot> 123
17:32 conal joined
17:35 andyhoang joined
17:39 mojjo joined
17:41 snowcrshd joined
17:42 approaching236 joined
17:45 patbecich joined
17:48 kaen_ joined
17:54 questioner111 joined
17:56 <questioner111> Hi, I'm reading the IO chapter of "real world haskell" and I'm wondering: what is an example of a case where you would use hGetContents and that whole flow of programming vs. just readFile and writeFile?
17:57 <srhb> questioner111: readFile and writeFile will read and write from/to files, not arbitrary handles :)
17:57 <srhb> questioner111: For instance, you couldn't easily use them to write to, say, stderr.
17:58 <questioner111> Great, thank you
17:59 slomo joined
18:00 hoffmeyer joined
18:07 <des_> can you pattern match in a helper function: foo (x:xs) = bar(x:xs) where bar = something x bar xs
18:08 <ski> pattern-match on what ?
18:08 <ski> an input parameter ?
18:08 <ski> something else ?
18:08 <ski> if the latter, use `case' (or maybe `let'/`where' or possibly a lambda, if there's only one alternative)
18:09 <monochrom> where bar (x:xs) =
18:10 <monochrom> A helper function is a function, tautologically. Do what you would do to all functions.
18:10 <des_> awww, thank you.
18:10 <geekosaur> also if you're using both the deconstructed (x:xs) and the original pattern, you can say something like ol@(x:xs) and use ol
18:10 mizu_no_oto_work joined
18:11 <monochrom> Yeah, foo ol@(x:xs) = bar ol
18:11 <monochrom> In fact may as well foo ol@(_:_) = bar ol
18:12 <des_> oh right. Because you wouldn't want to say say foo(x:xs) = bar xs
18:14 <des_> When you use a helper function like this, is it always in a tail position?
18:16 <ski> depends on "use .. like this" means
18:17 <des_> foo xs = bar xs where bar(x:xs)
18:17 <des_> is bar in a tail position?
18:18 <ski> `bar xs' is in tail position wrt the current call `foo xs'
18:18 <monochrom> This example is a tail call. But clearly not all helper functions are called by tail calls.
18:19 <monochrom> I don't think it is healthy to pay so much attention to this.
18:20 <des_> Thank you guys.
18:31 <WarmCookie> Is it true that, in general, function calls wont add stack frames? If so, worrying about tail call elimination is almost never necessary.
18:32 <monochrom> Yes. But it is true that evaluation still adds stack frames, sometimes.
18:34 nil_ joined
18:34 <geekosaur> WarmCookie, lazy languages work by graph reduction. there is no call stack because there are (modulo FFI) no calls. but there's an evaluation stack of graph nodes awaiting reduction of a different part of the graph, which can have similar yet noticeably different effects
18:34 <geekosaur> (in particular, the things on the stack are not what you'd expect from thinking of it as a "call stack")
18:37 giraffe joined
18:39 <ski> the stack is for storing away things you need to remember later
18:40 stef204 joined
18:41 joshuagross joined
18:42 joshuagross left
18:42 <ski> in a language implementation using call-by-value, an application `<expr> <expr 0>' will need to evaluate both the operator/function expression `<expr>' and the operand/argument/actual parameter expression `<expr 0>', before being able to continue evaluating the body of the function determined by evaluating `<expr>', with the formal parameter of that function bound to the result of evaluating `<expr 0>'
18:43 <ski> if it evaluates the operator `<expr>' first, then it needs to store the result of that away, on a stack, while evaluating the operand `<expr 0>', so that it can retrieve the function value the operand evaluated to after that
18:44 <ski> similarly, if it evaluates the operand before the operator instead, it needs to store away the value resulting from the operand evaluation during the evaluation of the operator
18:45 <ski> if the operator can't be a potentially complicated expression, perhaps only an identifier, then you can take any binary operator instead, to get the same effect
18:46 <nil_> Someone published a "map of algebraic structures" on /r/haskell about a week ago. Anyone got a link to that post?
18:46 <ski> the point is that it's not the calling of a function which requires stack space. it's the setting aside of some things you need to remember later, such as results of already evaluated operand expressions
18:46 systemfault joined
18:49 <ski> if we have a language implementation using call-by-need instead, then when evaluating an application `<expr> <expr 0>', we don't evaluate `<expr 0>', only `<expr>' (and then continue with evaluating the body of the identified function value, with the binding, as before, except the binding is now to an unevaluated expression)
18:49 <ski> so there's no intermediate result to remember while doing something else. this is what is meant by GHC not having a *call* stack
18:50 <monochrom> This is to a large extent why I don't make a big distinction between call stack and evaluation stack.
18:50 snowcrshd_ joined
18:51 <monochrom> You need a stack. And it can grow linearly. And you ought to know why and why not.
18:51 <ski> however, there's still other constructions which yields stack frames, such as `case <expr> of <pat 0> -> <expr 0>; ...'
18:51 <* ski> nods
18:51 <monochrom> And if you change evaluation order, then the why and why-not change too. This is tautological.
18:52 <ski> tail calls and tail recursion tends to be not quite as important in Haskell, because of the above, and because there's commonly other things one can do (writing an incremental operation)
18:52 <ski> but it's still important to know about tail calls
18:53 <monochrom> Stepping away further, you don't need a stack. But you need a space-time tradeoff.
18:53 <ski> (cue CPS)
18:54 <ski> WarmCookie ^
18:55 <monochrom> CPS "eliminates" stack but really it just rebrands stack frames as closures on the heap. http://www.vex.net/~trebla/haskell/cont.xhtml
18:56 hoffmeyer joined
18:56 <monochrom> But I know of a way to even reduce that space usage. The idea is to spend more time. Recall that the stack/heap is to remember "where should I return to". So don't remember it. Search for it every time.
18:57 <ski> hehe
18:58 <monochrom> which is largely what you did in highschool algebra when trying to crunch down a huge expression like sqrt((4+5)*(17-7)) / sin(...etc etc)
18:58 <monochrom> You would probably do a little search to decide that you want to do 4+5 first. Good choice.
18:59 <monochrom> And then you will copy-replace the whole expression.
18:59 malaclyps joined
18:59 <monochrom> And then you will search again for the next victim. You don't even bother to remember anything.
19:01 <monochrom> You will take quadratic time, but you won't need a stack or CPS.
19:01 Rodya_ joined
19:02 <monochrom> I wish 12 hours were enough to quickly implement a proof-of-concept Haskell interpreter to show this tomorrow. Stackless Haskell. The best April 1st idea ever.
19:03 <monochrom> Actually maybe I can just do vanilla lambda calculus. I already have a parser for it.
19:04 meck joined
19:04 binaryplease joined
19:06 davs joined
19:07 thoradam joined
19:08 <des_> if everything is curried in haskell, why do I need parens before head here: fst (head [("foo", "bar")])
19:08 <des_> why couldn't I just do this: fst head [("foo", "bar")]
19:09 sypwex joined
19:09 <monochrom> I don't think anyone ever said currying eliminates parentheses.
19:09 <monochrom> But when you see "x y z" the question is always "do you mean (x y) z, or do you mean x (y z)".
19:09 <nil_> des_: how would you parse (fst head xs)? Hint: things put next to each other is function application.
19:10 <monochrom> You choose one convention, and the other 50% of the people will be unhappy.
19:10 <monochrom> In the case of Haskell, the (x y) z people are happy, the x (y z) people are unhappy.
19:11 <ski> "everything is curried in haskell" is a misunderstanding
19:11 <ski> curried functions are a convention, not a property of the language (however the language does make it nice to use that convention)
19:11 <nil_> @favorofthegods++ ski
19:11 <lambdabot> Unknown command, try @list
19:12 <nil_> Eh...
19:12 <ski> the convention is about how to *represent* "multiple argument functions"
19:13 <ski> if we're to pass `f' two arguments, `x' and `y', then doing it the curried style would be `(f x) y', which can be abbreviated as `f x y' in Haskell
19:13 <ski> doing it the "tupled style" would be `f (x,y)'
19:14 <ski> if you look at e.g.
19:14 <ski> @type inRange
19:14 <lambdabot> Ix a => (a, a) -> a -> Bool
19:14 <ski> then it is using a mixture of curried and tupled style
19:14 <monochrom> The problem with loaded questions. Contain so many wrong and fictional assumptions.
19:15 davs joined
19:15 <ski> tupled style is nice when you want to group some arguments together, to think of them as a single compound thing (as in the pair of (lower & upper) index bounds, with `inRange')
19:15 <monochrom> And there are also many flawed explanations of currying out there.
19:16 <ski> curried style is nice when you want to partially apply (having decided on an ordering for which arguments you're more likely to want to partially apply over others)
19:17 <ski> currying is the process of going from tupled style to curried style. uncurrying is the reverse process
19:17 hoffmeyer joined
19:18 <ski> partial application is providing some (the "early"), but not all, of the arguments of a function, leaving a function that still expects the "late" arguments before computing the result
19:18 <ski> @type curry
19:18 <lambdabot> ((a, b) -> c) -> a -> b -> c
19:18 <ski> @type uncurry
19:18 <lambdabot> (a -> b -> c) -> (a, b) -> c
19:18 <ski> if we think of the former as
19:18 <ski> curry :: ((a,b) -> c) -> (a -> b -> c)
19:19 <ski> then (given `uncurriedF :: (a,b) -> c'), `curry uncurriedF' is the curried version (and mutatis mutandis for `uncurry')
19:19 <ski> however, if we think of it as
19:19 <ski> curry :: ((a,b) -> c) -> a -> (b -> c)
19:19 yellowj joined
19:20 <ski> then (given the same `uncurriedF' and also `x :: a'), `curry uncurriedF x' is *partial application* of `uncurriedF' to the early/first argument `x'
19:20 <ski> this ambiguity about what a use of `curry' can mean here is because we can think of this latter use of `curry' itself as being curried
19:21 <ski> if we instead define
19:21 <ski> partialApply :: ((a,b) -> c,a) -> (b -> c)
19:21 <ski> then `partialApply (uncurriedF,x)' is still partial application of `uncurriedF' to `x'
19:22 <ski> however, `partialApply' itself is now in tupled style. `partialApply' is the tupled/uncurried version of `curry' (iow `partialApply = uncurry curry')
19:22 <ski> enough confusing, yet ? :)
19:22 <des_> Haha. Yeah.
19:23 <des_> Can you give an example of a partial function and a curried function that is not partial
19:23 <ski> oh, i should also mention that currying is also good when you want to do some actual work in your function before getting the late argument(s)
19:25 <ski> e.g. one might have something like `match :: Regex -> (String -> Maybe Match)' that wants to do some analysis of the input `RegExp' before computing a more efficient function of type `String -> Maybe Match'. that way, `map (match myRegex) listOfString' will only do that analysis once. this is sometimes known as "run-time compilation" of the regex (or whatever you're doing analysis on)
19:25 <ski> "partial function" is unrelated to "partial application"
19:26 <nil_> This discussion is making me hate natural language. (And I love natural language.)
19:27 initiumdoeslinux joined
19:29 binaryplease joined
19:31 <monochrom> I have long decided to hate natural language. :)
19:31 <monochrom> In particular pronouns should die die die.
19:31 <des_> So, how would I create a function that could be partially applied? f x y = (+ x)
19:31 <nil_> monochrom: what's your native language?
19:31 <monochrom> Chinese.
19:32 <monochrom> Actually I started hating natural languages after English.
19:32 <nil_> Chinese has no pronouns if I'm not mistaken.
19:32 <monochrom> But I guess my complaints apply to Chinese just as well.
19:32 <monochrom> English merely adds prepositions and single-plural.
19:33 <monochrom> Chinese has pronouns too, don't worry.
19:33 <nil_> Okay.
19:33 <ski> des_ : `f x y = ..x..y..' or `f x = \y -> ..x..y..' or `f = \x -> \y -> ..x..y..' (abbreviated as `f = \x y -> ..x..y..') would be enough. put whatever result expression you want in place of `..x..y..', (possibly) depending on `x' respectively `y'
19:33 <* ski> must leave
19:33 <monochrom> My major complaints are presence of pronouns and lack of lexical scoping markers.
19:33 <des_> thank you
19:34 <ski> (then use `f (...)')
19:34 <monochrom> "sqrt((x+y) * (sin z - t)) / cos(e^(i*t))" You have no way to explain that in natural language because of my complaints.
19:36 <nil_> monochrom: good point.
19:36 <monochrom> Natural language is what disables people from grokking (((a -> b) -> r) -> r) -> ((a -> r) -> r) -> (b -> r) -> r
19:36 <monochrom> (See my http://lpaste.net/145254 for why we should care.)
19:39 <nil_> Did you type that out by hand or do you have a script that does that?
19:42 <monochrom> I typed it out by hand a long time ago. Today I just needed to go back to that paste and copy.
19:43 <monochrom> I am closer to a robot than the average human, so there is actually no need to draw a dichotomy between me and scripts. :)
19:43 alexelcu joined
19:44 davs joined
19:45 <nil_> I didn't mean to imply anything like that. :)
19:45 hvr joined
19:45 hvr joined
19:46 <jle`> it is ok, monochrom is actually a chat bot
19:46 <monochrom> Don't worry, I am on the side of the Daleks when they say "exterminate all humans"
19:46 <qu1j0t3> sounds healthy
19:47 <monochrom> Ah but lambdabot probably can do that expansion.
19:47 <monochrom> @unmtl Cont r (a -> b) -> Cont r a -> Cont r b
19:47 <lambdabot> Cont r (a -> b) -> Cont r a -> Cont r b
19:47 <monochrom> Hrm.
19:47 <monochrom> @unmtl Cont r (a -> b)
19:47 <lambdabot> ((a -> b) -> r) -> r
19:48 <monochrom> I guess unmtl is limited
19:48 <nil_> Pretty awesome chatbot imo.
19:51 davs joined
19:52 <qu1j0t3> ha
19:52 azahi joined
19:54 <nil_> So I was thinking of making up some fake news for tomorrow about someone finding a proof for the Riemann Hypothesis in their dishwasher user manual or something. Anyone feel like helping?
19:55 hoffmeyer joined
19:55 <monochrom> If it's a dishwasher user manual, I think a solution to the halting problem makes more sense.
19:56 nick_h joined
19:57 <monochrom> For maximum irony, it is the next discovered Mersenne prime whose hexadecimal form is the LaTeX code for a proof of the Riemann Hypothesis.
19:57 <nil_> I remember a good one from a few years back: ChessBase posted an article about how some folks exhausted the King's Gambit and found that it loses by force. It was rich.
19:58 <nil_> monochrom: I like the way you're thinking.
19:58 <monochrom> hehe
19:58 <monochrom> I love puns. I keep creating bad ones.
19:58 <monochrom> catmorphism :: (F r -> r) -> Meow F -> r
19:59 <jle`> i get it, it's because Meow sounds like Mu
19:59 <jle`> A+ pun, would read again
19:59 <nil_> :)
20:01 splanch joined
20:02 <qu1j0t3> nil_: That'd be a lovely easter egg if it were real. nice idea. maybe a novel ?
20:04 <nil_> qu1j0t3: I'm thinking more along the lines of an elementary math textbook.
20:05 <nil_> How compressible are proofs?
20:05 <nil_> Perhaps you could fit it in a One Direction song or something.
20:07 <qu1j0t3> i prefer the dishwasher manual idea. More Nicholson Baker
20:08 <nil_> Wait, I got the ultimate double swindle:
20:09 <nil_> Step 1. Discover proof (warning: might take thousands of years)
20:09 <nil_> Step 2. Publish proof on April 1
20:10 <nil_> Step 3. Everyone is shocked at first but they quickly realize it's April 1st and everyone has a good laugh.
20:10 <nil_> Step 4. Once the noise dies down point out the proof is real.
20:10 <nil_> Step 5. Everyone's like HOLY SHIT D:
20:11 <jle`> i believe that there have been a few notable legit-announcements-on-April-1st-that-were-initially-dismissed-as-jokes incidents in the past
20:12 <jle`> also, if i ever learn german, the first thing i would do was figure out how to turn that giant hyphenated word into one giant german word
20:12 malaclyps joined
20:12 <jle`> s/was/is
20:13 splanch joined
20:13 aarvar joined
20:14 <qu1j0t3> jle`: Yeah occupational hazard
20:14 <qu1j0t3> jle`: (re damn it, people will think this is fake!)
20:15 takle_ joined
20:15 splanch_ joined
20:15 <jle`> kind of like how mount everest was originally measured to be 29000. feet
20:15 <jle`> but they were sure people would think it was a rounded figure
20:15 <jle`> so they reported 290002 instead
20:15 <jle`> * 29002
20:16 takle joined
20:17 yellowj joined
20:17 systemfault joined
20:18 <qu1j0t3> :-)))
20:21 splanch joined
20:28 patbecich joined
20:38 andyhoang joined
20:38 <monochrom> There have also been honest jokes that became honest truths later. For example how SPJ would join Microsoft.
20:40 merijn joined
20:52 <qu1j0t3> i think if you live long enough, many honest jokes become honest truths
20:52 <qu1j0t3> viz. Brexit
20:52 <monochrom> yikes
20:52 <qu1j0t3> although. one might say dishonest.
20:54 uglyfigurine joined
20:56 sypwex joined
20:58 rjg_ joined
21:17 uglyfigurine joined
21:17 azahi joined
21:22 splanch joined
21:24 peterbecich joined
21:27 des_ joined
21:39 andyhoang joined
21:44 begriffs joined
21:48 pilne joined
21:49 jmorris joined
21:52 hiratara joined
21:52 albertus1 joined
21:57 MotherFlojo joined
21:57 pietilson joined
22:15 jmnk joined
22:15 mac10688 joined
22:20 splanch joined
22:23 louispan joined
22:31 hiratara joined
22:41 andyhoang joined
22:42 Rodya_ joined
22:54 emmanuel_erc joined
23:01 louispan joined
23:03 eacameron joined
23:16 splanch joined
23:22 splanch joined
23:34 mizu_no_oto_work joined
23:35 permegreen joined
23:41 andyhoang joined
23:45 jmiven joined
23:46 permagreen joined