Logs: freenode/#haskell
| 2021-04-06 14:19:09 | <zzz> | > (1 :: Num a => a) / 2 |
| 2021-04-06 14:19:11 | <lambdabot> | 0.5 |
| 2021-04-06 14:19:32 | <zzz> | > (1 :: Int) / 2 |
| 2021-04-06 14:19:33 | <lambdabot> | error: |
| 2021-04-06 14:19:34 | <lambdabot> | • No instance for (Fractional Int) arising from a use of ‘/’ |
| 2021-04-06 14:19:34 | <lambdabot> | • In the expression: (1 :: Int) / 2 |
| 2021-04-06 14:19:34 | <merijn> | That's GHC infers (and solves) a Fractional constraint there |
| 2021-04-06 14:19:41 | <zzz> | this is all good and obvious |
| 2021-04-06 14:19:44 | → | CaptainIRS joins (9d339880@157.51.152.128) |
| 2021-04-06 14:20:58 | → | notzmv joins (~zmv@unaffiliated/zmv) |
| 2021-04-06 14:21:11 | <zzz> | my problem is when i do 'x = 1 :: Num a => a ; y = x :: Int' i can do x/2 but not y/2 |
| 2021-04-06 14:21:25 | <merijn> | Yes |
| 2021-04-06 14:21:42 | <zzz> | which kind of clashes with my idea of referential transparency |
| 2021-04-06 14:21:50 | <maerwald> | tdammers: I've been thinking whether there's a way to capture the notion of code complexity (in terms of intellectual/practical complexity) better, especially over time. But it would always sorta be per compontent/module/function (e.g. via self-reports after a ticket is complete) |
| 2021-04-06 14:21:55 | <merijn> | zzz: Why? |
| 2021-04-06 14:22:02 | <maerwald> | But that quickly breaks down with code refactors |
| 2021-04-06 14:22:04 | → | jpds joins (~jpds@gateway/tor-sasl/jpds) |
| 2021-04-06 14:22:27 | × | tetrahedron quits (~hypercube@137.112.237.23) (Quit: WeeChat 3.1) |
| 2021-04-06 14:22:35 | <emmanuel_erc> | Given what has happened to me at this last job, it makes me wonder if persuing Haskell has been worth it or will be so. |
| 2021-04-06 14:22:45 | <merijn> | zzz: If you rewrote "y = 1 :: Int" you'd get the same result |
| 2021-04-06 14:22:57 | <maerwald> | emmanuel_erc: worth for? |
| 2021-04-06 14:23:03 | <zzz> | merijn: because if 'x = y', shouldn't 'x/2 == y/2' ? |
| 2021-04-06 14:23:04 | <merijn> | So, you can trivially replace 'x' with its definition in y. |
| 2021-04-06 14:23:29 | × | LKoen quits (~LKoen@65.250.88.92.rev.sfr.net) (Quit: “It’s only logical. First you learn to talk, then you learn to think. Too bad it’s not the other way round.”) |
| 2021-04-06 14:23:33 | <emmanuel_erc> | maerwald: Was learning Haskell worth it? (For job prospects/satisfication) |
| 2021-04-06 14:23:37 | <lortabac> | emmanuel_erc: instead of a big company with a small Haskell team, try targeting companies that are fully committed to Haskell |
| 2021-04-06 14:23:46 | <merijn> | zzz: But x and y have different types |
| 2021-04-06 14:23:54 | <tdammers> | maerwald: "WTF/s" is the established unit for that, I think |
| 2021-04-06 14:23:56 | <lortabac> | it has worked for me (I am starting a new job in a couple of weeks) |
| 2021-04-06 14:23:59 | <zzz> | merijn: i see |
| 2021-04-06 14:24:03 | <maerwald> | tdammers: :p |
| 2021-04-06 14:24:36 | <merijn> | zzz: You can replace sub expressions *in a well-typed expression* with their definition |
| 2021-04-06 14:24:46 | <merijn> | zzz: But your 'y/2' isn't well typed to begin with |
| 2021-04-06 14:24:52 | <maerwald> | emmanuel_erc: well, there are some well paid haskell jobs, but generally you can make better money with other languages |
| 2021-04-06 14:25:02 | <tdammers> | emmanuel_erc: I would say that learning Haskell is worth it even if you never get to use the language itself professionally. Just the concepts you're exposed to, and the clarity gained from working through them and making them your own, is worth every minute of it. |
| 2021-04-06 14:25:22 | <merijn> | zzz: Basically, claims are limited to well-typed expression. Expression that are *not* well-typed may (or may not) conform to those claims |
| 2021-04-06 14:25:24 | <tdammers> | emmanuel_erc: the risk is of course that you may end up spoiling your brain for more, ahem, pedestrian languages |
| 2021-04-06 14:25:33 | <maerwald> | pedestrian :p |
| 2021-04-06 14:25:44 | <merijn> | zzz: In this case, the claim would still hold for your example, despite 'y/2' not being well-typed |
| 2021-04-06 14:25:46 | <tdammers> | *cough*phpedestrian*cough**diescoughing* |
| 2021-04-06 14:26:03 | <emmanuel_erc> | tdammers: Yeah, I can sympathize with that last statement. It annoys me when I don't have algebraic data types (I'm talking the most basic kind). |
| 2021-04-06 14:26:22 | <maerwald> | emmanuel_erc: you can *sorta* have them in typescript |
| 2021-04-06 14:26:30 | <kuribas> | tdammers: that happened. I find every other language painful. |
| 2021-04-06 14:26:39 | <merijn> | zzz: Basically, the idea of interactions between proofs/claims and types is that, to keep our proofs doable, we restrict to proving properties of well-typed expressions |
| 2021-04-06 14:26:43 | <maerwald> | and there are way more opportunities in typescript, so if you're looking for that only... |
| 2021-04-06 14:26:58 | <merijn> | zzz: Making use of the type system to rule out cases that we don't care about |
| 2021-04-06 14:27:35 | <tdammers> | emmanuel_erc: algebraic data types are still a relatively superficial feature. I'm talking more about the big picture. Things like being more aware of side effects, and designing code to keep them contained. Even if your code isn't pure the way Haskell code is, just having the clarity of mind to realize that effects are thing that need particular attention, and understanding some strategies for dealing with |
| 2021-04-06 14:27:37 | <tdammers> | them, is worth a lot. |
| 2021-04-06 14:27:54 | <merijn> | zzz: Consider the trivial type system where no expressions are well-typed. Now all our proofs are trivial! Everything is always true for all well-typed expressions ('cause there aren't any)! |
| 2021-04-06 14:28:05 | <maerwald> | tdammers: rust sharpens your mind too about mutability, just in a different way |
| 2021-04-06 14:28:17 | <tdammers> | maerwald: no doubt. |
| 2021-04-06 14:28:20 | <zzz> | merijn: that used to be my intuition, but then 'x = 1 ; y = x :: Int ; z = x :: Double' gives me an error |
| 2021-04-06 14:28:23 | <merijn> | zzz: Vice versa, consider the untyped case where *everything* is well-typed, now proving anything becomes impossible |
| 2021-04-06 14:28:23 | <haskellstudent> | i would have said just having any decent static type system is a huge improvement |
| 2021-04-06 14:28:30 | <tdammers> | maerwald: rust also wasn't the first thing I thought of when I said "pedestrian" |
| 2021-04-06 14:28:31 | <merijn> | zzz: Ah! |
| 2021-04-06 14:28:36 | → | bahamas joins (~lucian@unaffiliated/bahamas) |
| 2021-04-06 14:28:37 | × | ddellaco_ quits (~ddellacos@ool-44c73afa.dyn.optonline.net) (Remote host closed the connection) |
| 2021-04-06 14:28:39 | <emmanuel_erc> | rust is even more esoteric than Haskell in some ways |
| 2021-04-06 14:28:40 | <merijn> | zzz: That one is a kinda funny edge case |
| 2021-04-06 14:28:55 | <maerwald> | I can be convinced to do haskell, rust and typescript. They all have ADTs |
| 2021-04-06 14:28:56 | <merijn> | zzz: You have discovered the "Dreaded Monomorphism Restriction" |
| 2021-04-06 14:29:01 | <haskellstudent> | esoteric? :) |
| 2021-04-06 14:29:01 | <emmanuel_erc> | well esoteric isn't the right word... there are less use cases for rust IMO |
| 2021-04-06 14:29:07 | <tdammers> | yeah, having a type system and type checker that actually pull their weight can do wonder to the damage that Java and its brethren may have inflicted on your brain |
| 2021-04-06 14:29:12 | × | v01d4lph4 quits (~v01d4lph4@223.177.183.124) (Remote host closed the connection) |
| 2021-04-06 14:29:12 | <maerwald> | emmanuel_erc: it's verbose af, but pretty neat |
| 2021-04-06 14:29:25 | <merijn> | zzz: Which is actually kinda related to your original question |
| 2021-04-06 14:29:30 | → | tanuki joins (~quassel@173.168.178.1) |
| 2021-04-06 14:29:46 | <zzz> | merijn: oh i see |
| 2021-04-06 14:29:52 | <merijn> | zzz: Since '1' is polymorphic it can be used at infinitely many different types, right? |
| 2021-04-06 14:30:20 | <merijn> | zzz: Now, logically, you can't keep infinite different values in memory, so your only other option is to compute them every time their used |
| 2021-04-06 14:30:32 | <maerwald> | and verbose languages (like C) have the tendency to make you skip lines of code in order to understand the broad meaning... and then there's this huge gap between high-level and actual understaning (including all the memory tricks in a codepath) |
| 2021-04-06 14:30:33 | <zzz> | i would think so. but i have an idea of what you are talking about i've encountered it before |
| 2021-04-06 14:30:35 | → | rj joins (~x@gateway/tor-sasl/rj) |
| 2021-04-06 14:30:36 | <merijn> | zzz: But assume '1' was instead something that was super expensive to compute. That'd be bad |
| 2021-04-06 14:31:18 | <merijn> | zzz: We have the situation where 'x = ...' *looks* like it is a value that's only computed once, but ends up computed many times...that'd be bad |
| 2021-04-06 14:31:21 | × | kritzefitz quits (~kritzefit@2003:5b:203b:200::10:49) (Remote host closed the connection) |
| 2021-04-06 14:31:43 | <haskellstudent> | emmanuel_erc: afaik a simple way to put it is that rust is better if performance and latency (no gc pauses) and/or memory usage is really important. haskell is more high level but has gc with the pros and cons of that, its harder to reason about performance and memory usage. |
| 2021-04-06 14:31:59 | <zzz> | merijn: yes |
| 2021-04-06 14:32:06 | <merijn> | zzz: So the monomorphism restriction says "if something *looks* like a value (as opposed to a function), we monomorphise it" this guarantees the expected "constant computation time" |
| 2021-04-06 14:32:14 | <maerwald> | pick the language your engineers like, whatever that is :) |
| 2021-04-06 14:32:20 | <emmanuel_erc> | haskellstudent: Yeah, I realize that distinction. |
| 2021-04-06 14:32:21 | <haskellstudent> | emmanuel_erc: but i also found rust pretty viable for building an API backend service |
| 2021-04-06 14:32:33 | <merijn> | zzz: But that only works if it *can* be monomorphic. But you example tries to turn it into both Int *and* Double |
| 2021-04-06 14:32:46 | <emmanuel_erc> | haskellstudent: Have you tinkered around with rust + webassembly? |
| 2021-04-06 14:32:49 | <merijn> | zzz: That's only possible if 'x = 1' was polymorphic, which we just said was tricky |
| 2021-04-06 14:33:11 | × | bahamas quits (~lucian@unaffiliated/bahamas) (Ping timeout: 240 seconds) |
| 2021-04-06 14:33:15 | → | mkDoku joins (~TheMule@aftr-37-201-195-134.unity-media.net) |
| 2021-04-06 14:33:32 | <merijn> | zzz: If you wrote your original example as 'x :: Num a => a; x = 1' (so explicit polymorphic literal) then 'y :: Double; y = x' and 'z :: Int; z = x' *would* work |
| 2021-04-06 14:34:00 | <merijn> | (The polymorphic type signature on 'x' saying "I know what I'm doing, I'm okay with recomputing this for all possible values" |
| 2021-04-06 14:34:06 | <merijn> | ) |
| 2021-04-06 14:34:10 | <haskellstudent> | emmanuel_erc: i have a couple months experience each with both haskell (and a bit with ghcjs) and rust but didnt try webassembly because it still seems a bit too early for that. it seems like webassembly bundles turn out even bigger than what ghcjs produces? |
| 2021-04-06 14:34:50 | <dolio> | Wow, that's hard to believe. |
| 2021-04-06 14:36:01 | → | ddellaco_ joins (~ddellacos@ool-44c73afa.dyn.optonline.net) |
| 2021-04-06 14:36:01 | <haskellstudent> | emmanuel_erc: for frontend i tried miso and i found it pretty quick go get started with and the minified and gzipped js is around 100k minimum. i am currently evaluating reflex so i have no opinion on it yet but the minimum js size turns out around 200k IIRC |
| 2021-04-06 14:36:36 | <zzz> | merijn: so in conclusion, be dilligent with your signatures |
| 2021-04-06 14:37:05 | <maerwald> | haskellstudent: hasn't ghcjs development basically stalled? |
| 2021-04-06 14:37:33 | → | frozenErebus joins (~frozenEre@37.231.244.249) |
| 2021-04-06 14:37:45 | <haskellstudent> | maerwald: not at all as far as i can tell? both miso and reflex/obelisk seem to be actively maintained and used in production |
All times are in UTC.