Skip to content

Instantly share code, notes, and snippets.

@betehess
Last active November 29, 2017 09:06
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save betehess/77de5b4b35ae11801936 to your computer and use it in GitHub Desktop.
Save betehess/77de5b4b35ae11801936 to your computer and use it in GitHub Desktop.
On freenode/#scalaz this morning
<RaceCondition> can I use Scalaz to get exhaustion checks when matching on numeric values? Scala obviously doesn't do that
<RaceCondition> ! 1.1 match { case x if 0.0 <= x && x < 0.5 => "bad"; case x if 0.5 <= x && x <= 1.0 => "good" }
<dibblego> doubt it
<multibot_> scala.MatchError: 1.1 (of class java.lang.Double)
<multibot_> ... 38 elided
<dibblego> use types though?
<RaceCondition> wdym?
<dibblego> use a type to note each range
<dibblego> you want a floating-point between 0.0 and 1.0?
<RaceCondition> wouldn't that just move the problem to a different stage?
<dibblego> yes, to the earliest possible stage
<RaceCondition> I'd have to convert the Double to that type, at which point I'd still use matching, at which point I'd like the compiler to warn me if I've forgotten a range :)
<dibblego> that's the point of types after all
<RaceCondition> so the question remains
<dibblego> you'd have to not start with a Double
<qu1j0t3> RaceCondition: you are talking about classification. Just classify
<qu1j0t3> RaceCondition: then match on the classification
<dibblego> why do you have a Double? from where did it come from?
<RaceCondition> qu1j0t3: that code IS the classification code btw
<qu1j0t3> right
<dibblego> how do you know it is "bad"?
<qu1j0t3> that's another good question.
<dibblego> what invariant made that the case?
<qu1j0t3> what would an exhaustiveness check on a Double mean
<RaceCondition> ! 1.1 match { case x if 0.0 <= x && x < 0.5 => "bad"; case x if 0.5 <= x && x <= 1.0 => "good" }
<multibot_> scala.MatchError: 1.1 (of class java.lang.Double)
<multibot_> ... 38 elided
<qu1j0t3> see my question in the other channel... there are values that are not in [-∞,∞]
<qu1j0t3> etc, etc.
<dibblego> type error > warning
<RaceCondition> the match expression obviously doesn't cover < 0 and > 1.0 — that could be statically detected
<dibblego> it could yes
<qu1j0t3> eCondition | qu1j0t3: that code IS the classification code btw
<qu1j0t3> oops
<qu1j0t3> i mean, what about this question:
<qu1j0t3> dibblego | why do you have a Double? from where did it come from?
<RaceCondition> from a mathematical computation that computes certain scores for people
<dibblego> something makes you think it is in that range
<dibblego> fix that bit
<RaceCondition> but look, this might as well be a Double that can actually range from -Inf to Inf... then I'd still have the same question
<RaceCondition> I'm not saying there aren't workarounds
<dibblego> same answer
<dibblego> this question generalises to "use types"
<dibblego> how do I know my Int is a valid age?
<dibblego> well how indeed? how did you even come to that conclusion?
<dibblego> well, because age returns Int
<dibblego> stop doing that!
<dibblego> Age returns a value between 0 and MAX_AGE
<dibblego> oh, then you want a type for that
<dibblego> but what about my Int!
<dibblego> there was never an Int
<dibblego> but I want to use it as an Int!
<dibblego> so do that
<dibblego> but it is clumsy and annoying to convert all the time!
<dibblego> so use libraries
<dibblego> which library?
<dibblego> well, in this case, lenses
<dibblego> or prisms or whateva
<dibblego> but now I have to learn lens!
<RaceCondition> at some point I still have to convert Int => Age
<dibblego> yes, you do
<dibblego> Nope.
<dibblego> do you know how I know you dont have that point?
<dibblego> because *nobody does because it does not exist*
<dibblego> go on then, convert 3333 to Age
* dibblego twiddles
<dibblego> how do I get the (a) out of (IO a)?
<dibblego> you don't
<dibblego> but I need the (a)!
<dibblego> so get it
<dibblego> but how?
<dibblego> libraries
<dibblego> what do you mean libraries!?
<dibblego> you know, like say, the IO monad
<dibblego> but now I have to learn monads!
<dibblego> yes, you do
<dibblego> but I want the (a) out of (IO a)!
<dibblego> no you don't!
<dibblego> yes I do, don't tell me what I want!
<dibblego> well, I know you don't want it, because it is *not a thing that exists*
<dibblego> gah, but I want things that don't exist
<dibblego> yes, I want puppies all over my face right now, doesn't exist
<dibblego> IO is a terrible example of course
<dibblego> how about this one
<dibblego> how do I get the A out of (B => A)?
<dibblego> you give it a B
<dibblego> but I don't have a B!
<dibblego> then you don't have an A
<dibblego> but I need it!
<dibblego> libraries
<dibblego> (or doesn't exist)
<dibblego> of course, you might have f(x) is believed to always return an Int in Age range
<dibblego> but unfortunately, some assclown made f return Int
<dibblego> and so, you draw a line in the sand and say, "enough! no more assclowns from here on!"
<RaceCondition> if I have Age1, Age2, Age3, etc upto Age<Max>, and say, also, AgeInvalid, I'd still want exhaustion checks in my rawAge match { ... } expression so as to make sure I didn't forget the `case _ => AgeInvalid` bit
<dibblego> then you fix it at that point
<dibblego> that's what really happens
<dibblego> that's just Option[Age] — you have exhaustion checks
<dibblego> you really want a *type error*
<dibblego> these are just limitations of impredicate logic
<dibblego> in light of this, scala says, "you know, I may be wrong here, but you probably want to do the Invalid/None case"
<RaceCondition> so what is the purpose of exhaustion checks in the first place then?
<dibblego> that is an exhaustion check — a sad consolation
<dibblego> to make up for the limitations of the type system in this case
<RaceCondition> if I validate input then the type system can't help me
<dibblego> the benefit is expressiveness on a turing machine
<RaceCondition> user input, I mean
<dibblego> sure it can
<RaceCondition> maybe I don't want a type error
<RaceCondition> maybe I actually have categories for each possible value of a Double
<RaceCondition> or Int
<dibblego> then what? a program that doesn't work?
<dibblego> so do that too
<RaceCondition> in which case I'd still want exhaustion checks in `rawInt match { ... }`
<dibblego> you can say, Int => Option[Age] you know
<dibblego> n => if(inRange(n)) Some(Age(n)) else Nope
<dibblego> exhaustion checks are a desperate last resort
<dibblego> use types
<RaceCondition> the point of exhaustion checks is to help me not forget a range
<dibblego> no that is the point of type errors
<RaceCondition> matter of opinion
<dibblego> nope
<RaceCondition> OCaml and Haskell rely more heavily on exhaustion checks
<dibblego> my opinion is that working programs are more valuable than not working programs
<dibblego> no they don't
<dibblego> thousands and thousands of lines of haskell and you know what? not a single inexhaustive check
<dibblego> that's because: types, dunrite
<dibblego> I bladdy well made it that way
<dibblego> beginner haskell programmers rely on them
<dibblego> well, not all of them — not when I am finished with them
<dibblego> show me this heavy reliance and I will show you a better program without it
<RaceCondition> why would my sealed trait Foobar get exhaustion checks but not Int? Int is also an "enumeration"
<dibblego> because checking exhausation on *everything* is the same as solving the halting problem
<dibblego> that's why you strive for safety in the first place, instead of conceding to exhaustive checks
<RaceCondition> you mean exhaustion checks on Ints are in general impossible to achieve?
<dibblego> I am quite exactly doing this right now you know
<dibblego> no, on everything in genera
<dibblego> do you know a WGS84 latitude/longitude?
<dibblego> is that an Int?
<dibblego> nope
<dibblego> but it is 73 degrees! it is an Int!
<dibblego> stop it
<dibblego> types
<RaceCondition> it'd have sufficed to just use `case n if n * n > 100` as an example, and I would have believed you right away.
<dibblego> I don't know what that means
<dibblego> I gave several examples
<dibblego> I'm not asking you to believe me
<dibblego> you might value not-working programs after all
<RaceCondition> I already do; I just don't see a need for that wall of text
<dibblego> the moment you don't, well, facts have something to say
<RaceCondition> nor the sarcasm
<dibblego> oh excellent, I should have just said at the start: types
<dibblego> (which I did)
<RaceCondition> that's a different point...
<dibblego> ugh
<RaceCondition> it's not the same as "ints simply can't be exhaustion checked"
<RaceCondition> types are just a solution to that limitation, which I agree with
<dibblego> you'll note that I didn't say that
<dibblego> and when you asked, I repeated, no, I didn't say that
<dibblego> but hey, sure, yes
<dibblego> whichevz
<RaceCondition> you said: "no, on everything in genera" which also includes ints
<dibblego> no, it really doesn't
<RaceCondition> so ints can be exhaustion checked? :)
<dibblego> jesus fuck me drunk christ
<RaceCondition> I've never seen that style of speech/attitude on #scalaz btw; but I guess there's always a first time
<dibblego> oh talk police now?
<RaceCondition> I'll get back to work now
<dibblego> k bye
<RaceCondition> swearing is fine but the "you're stupid I'm smart" attitude puts people off
<dibblego> yes thank you for that advice I will take it into consideration
<dibblego> fucking hell
<dibblego> go to work
<dibblego> "I am OK if you say those words, but not those other ones"
<dibblego> by the way, go fuck yourself, a little bit?
<RaceCondition> rinse and repeat? :)
<dibblego> I don't give a flying fuck for imposed morality, especially when it is cheap and bullshit
<RaceCondition> I agree with that, dibblego
<dibblego> excellent
<dibblego> have fun at work
<dibblego> use types!
<RaceCondition> I do, thanks
<dibblego> @pl \b r -> pure (b (r n))
<lambdabot> (pure .) . (. ($ n))
<dibblego> @pl \r -> pure (b (r n))
<lambdabot> pure . b . ($ n)
<dibblego> @type bool id
<lambdabot> (a -> a) -> Bool -> a -> a
<ceedubs> dibblego: It looks to me like RaceCondition was asking a question in good faith. I want #scalaz to be a place where that is welcomed.
@betehess
Copy link
Author

betehess commented Oct 2, 2014

Bullying is never ok.

@djspiewak
Copy link

Bullying is never ok.

Also explicitly against the Typelevel code of conduct. The sad thing is that there's good information in here, just punctuated by completely useless and extraneous insults and sarcasm.

@nuttycom
Copy link

nuttycom commented Oct 8, 2014

If you ask me, dibblego was being extremely patient here, and was getting nowhere. Not once does RaceCondition ask the very sensible question, "I don't understand, how can I use types to help me here?" Instead it's just bullshit.

@djspiewak
Copy link

As I said on Twitter, there is categorically no excuse for this sort of behavior. If he was out of patience, the correct action is to say nothing at all. What he did is toxic to his own reputation and the reputation of the community, and this is precisely the sort of issue that I have always had with Tony. He's a brilliant guy, and as I said, there is some very good and helpful answers buried in the dross. However, if you can't say something with a level of courtesy and respect, then don't say it at all. How you say something matters as much or more than what you say.

He's not helping RaceCondition here or really anyone else, so what purpose does it serve? Answer: none other than venting his own frustration.

@puffnfresh
Copy link

yes, I want puppies all over my face right now, doesn't exist

There's no excuse for this sarcasm Tony.

But seriously, I didn't read carefully but I see RaceCondition being not nice here and dibblego returning the favour. What's up?

@djspiewak
Copy link

But seriously, I didn't read carefully but I see RaceCondition being not nice here and dibblego returning the favour. What's up?

I see RaceCondition failing to understand some things about how nominal type systems are used to validate higher level constraints, and that's precisely what Tony is trying to explain (and he does explain it, in between his uh, other comments). I see him getting frustrated about 2/3rds of the way through, after Tony had already turned on the snark.

@puffnfresh
Copy link

RaceCondition and I worked out that matter in privmsg in about 5 minutes by the way

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment