Logs on 2023-10-16 (liberachat/#haskell)
| 00:00:11 | <geekosaur> | if there is no such instance for whatever type `a` works out to be, the `Show a` constraint fails |
| 00:00:46 | <monochrom> | You know, I'll just shameless plug my course notes last summer https://www.cs.utoronto.ca/~trebla/CSCC24-2023-Summer/ . Or you could study any other Haskell tutorials. |
| 00:00:46 | × | misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 255 seconds) |
| 00:03:39 | <jumper> | #ifdef Show::a \n String show(a){...} \n #endif |
| 00:04:02 | <jumper> | show:: Show a => a -> String |
| 00:04:41 | → | bilegeek joins (~bilegeek@2600:1008:b02f:1011:22e7:78e8:8a34:1aa8) |
| 00:04:44 | <monochrom> | I'm afraid that analogy breaks in multiple ways. |
| 00:05:12 | <monochrom> | And by the time you successfully describe the one way it doesn't break and so it is what you mean, |
| 00:05:27 | <monochrom> | we may as well skip the analogy and just say directly what you mean. |
| 00:05:37 | <Inst> | so monochrom, you'd suggest this? |
| 00:05:38 | <Inst> | https://www.cs.utoronto.ca/~trebla/CSCC24-2023-Summer/04-haskell-types-2.html |
| 00:05:45 | <Inst> | that's the discussion of typeclasses |
| 00:05:49 | <monochrom> | That's what's wrong with all analogies. All of them. They are more like insider jokes. |
| 00:05:57 | <monochrom> | Yes. |
| 00:06:28 | <monochrom> | But earlier lectures also have lambdas and why we write like "Int -> Bool -> Char" and "f x y" and what they mean. |
| 00:08:30 | <Inst> | what would you do in that scenario, then? as in, you know the learner has a misconception, you want to tilt them in the right direction, but you're afraid of capsizing them into some rabbit hole? |
| 00:08:56 | <monochrom> | I don't have a general algorithm for that. |
| 00:09:15 | <monochrom> | From past experience, every individual case admits its own simple solution. |
| 00:09:28 | <Inst> | only after careful consideration of every individual case |
| 00:10:57 | <monochrom> | One example that comes to mind is someone wrote "x = 2*x + 1" and wondered why it didn't mean solving for x in the popular sense. |
| 00:11:31 | <Inst> | i've heard about that, i.e, assignment is actually alien to people learning programming for the first time |
| 00:11:35 | <Inst> | or rather, reassignment |
| 00:11:50 | <monochrom> | My solution did not even bring up "it does solve for x, but in the information order sense" (which would be technical true actually, see my "partial order theory of recursion blahblah") |
| 00:12:32 | <monochrom> | The simple solution was "recall zs = 0 : zs. so this is recursion. except x = 2*x + 1 is the non-terminating kind." |
| 00:13:25 | <jumper> | show :: Show a => a -> String != String show(Show.a){...} ? |
| 00:14:06 | <monochrom> | I think I don't know what "String show(Show.a){...}" means. |
| 00:14:40 | <Inst> | bleh, typeclasses is the easy way, which is why it was a mistake to get into this rabbit hole |
| 00:15:07 | <Inst> | class Show a where |
| 00:15:09 | <Inst> | ... |
| 00:15:12 | <Inst> | declaration of a typeclass |
| 00:15:38 | <Inst> | there's a type signature of show, there, should be show :: a -> String |
| 00:15:38 | <geekosaur> | jumper, there is no analogy that will help you |
| 00:15:39 | <jumper> | monochrom, is it even possible to describe it in C? |
| 00:15:45 | <geekosaur> | they're all going to be incorrect |
| 00:16:02 | <Inst> | instance Show Int where |
| 00:16:03 | <Inst> | ... |
| 00:16:23 | <Inst> | where it's an impleemntation of the function Show where a is Int |
| 00:16:47 | <monochrom> | Yes it is possible because Haskell can be compiled to C, so I could just show you the result of compilation. No it is useless, you wouldn't even learn Java by compiling to any other language. |
| 00:16:56 | <Inst> | if there's no instance Show Foo for your type |
| 00:17:11 | <Inst> | erm, the function show |
| 00:17:26 | <Inst> | not Show, because functions cannot start with a capital letter in Haskell |
| 00:17:45 | <monochrom> | Hell, you wouldn't even learn C++ by translating to C. |
| 00:18:12 | <Inst> | if there's no instance Show Foo for your type, your code won't compile because of the constraint |
| 00:18:17 | <jumper> | monochrom, eh, that's how I learned C++ |
| 00:18:23 | <monochrom> | Despite even the fact that the 1st version of C++ was just a lot of C macros, or something close to that. |
| 00:18:26 | <jumper> | C with classes :D |
| 00:19:07 | <monochrom> | Did you actually translate C++ classes to classless C? |
| 00:19:11 | nitrix-or-treat | is now known as nitrix |
| 00:19:32 | <monochrom> | Because I am not going to translate type class Haskell to type-class-less C either. |
| 00:19:33 | <jumper> | monochrom, the concept of a class I learned by making classes in C |
| 00:19:43 | <Inst> | I'm told there are some ancient courses where you learn C++ by implementing it in C, but that was back when C++ and C were more closely related |
| 00:19:45 | <monochrom> | OK so you did. |
| 00:20:01 | <monochrom> | Then look for "dictionary passing" I guess. |
| 00:20:47 | <Inst> | but where did I lose you, jumper? |
| 00:21:07 | <jumper> | Inst, what do you specifically mean? |
| 00:21:19 | <monochrom> | Perhaps insisting on a translation to a familiar language? |
| 00:21:32 | <Inst> | like, the explanation of how => is used to specify constraints on type variables? |
| 00:21:44 | <monochrom> | I mean, I am not exempt from that, either. |
| 00:21:51 | <jumper> | The concept "Constraint" is what I'm trying to define |
| 00:22:12 | <monochrom> | Just that I insist on translating to math (the denotational way), and therefore I have actually had great success. |
| 00:22:44 | <Inst> | the type variable a, in that type signature, can be any normal type |
| 00:23:05 | <Inst> | you're constrainting it because the code only makes sense if the constraint applies |
| 00:23:14 | <monochrom> | When I was young and arrogant, I even said the following: |
| 00:23:37 | <Inst> | if there's no implementation of Show and show for that type, what is the function supposed to do? |
| 00:23:39 | <monochrom> | "The language of CS is not C, or Pascal, or even Lisp Prolog etc. The language of CS is math." |
| 00:23:59 | <jumper> | monochrom, true |
| 00:24:09 | <monochrom> | Arrogant but actually right on and successful. |
| 00:24:44 | <jumper> | Inst, "a" is a type right? show :: Show a => a -> String |
| 00:24:55 | <Inst> | it's a type variable, which means, any "normal" type |
| 00:25:27 | <Inst> | Show a constrains a to mean "any type that has an instance declaration for Show" |
| 00:25:46 | × | [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 260 seconds) |
| 00:26:44 | <jumper> | so "a Show" has to exist? |
| 00:27:22 | <nitrix> | Other way arounds, instances like Show Int, Show Float, etc have to exists to be able to use show on them. |
| 00:28:42 | <nitrix> | So Int would implement show :: Show Int => Int -> String, Float would implement show :: Show Float => Float -> String, so on. |
| 00:29:13 | <Inst> | ^^^ |
| 00:29:49 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 00:29:51 | <jumper> | I'm blind, I'm not seeing the pattern. What is "Show"? |
| 00:30:03 | <Inst> | class Show where |
| 00:30:10 | <Inst> | excuse me |
| 00:30:13 | <Inst> | class Show a where |
| 00:30:19 | <Inst> | show :: a -> String |
| 00:30:34 | <Inst> | iirc, it's more complicated than that, but this is just a simplification |
| 00:30:34 | <nitrix> | `Show a` is a typeclass. `Show Int` is an instance of that typeclass. `Show` alone is more complicated, it's a type constructor. |
| 00:31:43 | <Inst> | show here is defined in the typeclass only by its type signature |
| 00:31:49 | <Inst> | you need an instance declaration |
| 00:31:53 | <Inst> | instance Show foo where |
| 00:32:03 | <Inst> | to have the actual function |
| 00:32:07 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:58fe:b85d:458c:ca9c) (Remote host closed the connection) |
| 00:32:30 | <Inst> | for that particular type |
| 00:33:00 | → | _xor7 joins (~xor@72.49.199.93) |
| 00:33:48 | <jumper> | Inst, should I dissect this syntax that you wrote: "class Show a where \n show :: a -> String"? Am I understanding correctly that you're trying to refer that show is a member of Show? |
| 00:34:00 | <Inst> | it's a haskell typeclass, not an OOP class |
| 00:34:20 | <Inst> | it's closer to an interface, it's defining a bunch of names (values or functions) |
| 00:34:45 | <Inst> | the names are overloaded based on the type |
| 00:35:31 | <nitrix> | The type class represents a group of types and it comes with a contract. The types that wants to belong in that group have to implement the functions the specified in the contract. |
| 00:35:52 | × | _xor quits (~xor@72.49.199.93) (Ping timeout: 255 seconds) |
| 00:35:52 | _xor7 | is now known as _xor |
| 00:36:41 | <nitrix> | Here, types that wants to be be showable (printable to a string) needs to implement the instance with a reasonable show function. |
| 00:37:20 | <Inst> | it's sort of a mess, I really shouldn't have started this |
| 00:37:30 | <Inst> | nitrix: what jumper really wants to know right now is what => does in a Haskell context |
| 00:37:41 | <Inst> | he is really, really new |
| 00:38:17 | <nitrix> | Well, you're reasonably there already with the idea of constraining type variables to specific type classes. |
| 00:38:37 | <geekosaur> | if you really want to know, Show a => translates to the Show instance dictionary for type a |
| 00:38:40 | <Inst> | he doesn't know what a typeclass is, because he was asking about what the function arrow is |
| 00:39:17 | <geekosaur> | if you specify something like (Show a, Monad m) => then it translates to a tuple containinjg the Show instance dictionary for a and the Monad instance dictionary for m |
| 00:39:18 | <nitrix> | You can have more than one constraint also. sort :: Eq n, Ord n => [n] -> [n], etc. |
| 00:39:46 | <nitrix> | Forgot the parens. |
| 00:39:52 | <Inst> | in this case, Eq is actually easier to deal with, tbh |
| 00:40:02 | <Inst> | (==) is the member of Eq, jumper |
| 00:40:04 | <geekosaur> | and m will be determined at call sites and the appropriate instance declaration must be in scope |
| 00:40:16 | <geekosaur> | "a and m" |
| 00:40:17 | <Inst> | when you use ==, you're not calling a language primitive, but rather, you're calling a library-defined function |
| 00:40:27 | → | ddellacosta joins (~ddellacos@ool-44c738de.dyn.optonline.net) |
| 00:40:32 | <Inst> | the language starts by reading the types of the arguments to == |
| 00:40:58 | <Inst> | then looks up the correct version of == for those types |
| 00:41:20 | <Inst> | anyways, this is one reason people are pissed off at me, monochrom |
| 00:41:26 | <Inst> | sorry, i should have just walked off |
| 00:41:58 | <geekosaur> | I think here the real problem is jumper is insisting we give them C |
| 00:42:02 | <geekosaur> | and we can't |
| 00:42:27 | <geekosaur> | well, we could, but it'd be a lot of code implementing the whole typeclass mechanism |
| 00:42:58 | <nitrix> | And the higher-kinded stuff too :] |
| 00:43:02 | <nitrix> | ,k (=>) |
| 00:43:24 | <nitrix> | I've been away from #haskell for so long, how do you trigger lambdabot again? |
| 00:43:26 | <Inst> | (=>) is raw syntax, isn't it? |
| 00:43:32 | <geekosaur> | :k (=>) |
| 00:43:33 | <lambdabot> | error: parse error on input ‘=>’ |
| 00:43:51 | <geekosaur> | but as I suspected, it doesn';t do that because => is syntax, not an operator |
| 00:44:12 | <nitrix> | Interesting. I recall (=>) having some fancy Constraint -> * -> * kind. |
| 00:44:29 | <nitrix> | Maybe figuratively. |
| 00:44:47 | <geekosaur> | (what type does it need to be to support both Constraint => and (Constraint a, Constraint b) =>?) |
| 00:44:59 | <geekosaur> | or kind or sort or etc. |
| 00:45:11 | <nitrix> | Obviously we need kindclasses :P |
| 00:45:46 | <monochrom> | Unpopular opinion: I hate "typeclass", I prefer "type class". And the Haskell Report agrees. |
| 00:46:09 | <Inst> | btw, here's something interesting |
| 00:46:17 | <Inst> | at least in ghci, if you: |
| 00:46:19 | <nitrix> | I think I used to have an opinion on that but it's long gone. |
| 00:46:19 | <Inst> | data Foo = Foo |
| 00:46:26 | <monochrom> | Unpopular opinion #2: "The Maybe type" is OK. And the Haskell Report agrees. >:) |
| 00:46:28 | <Inst> | instance Show Foo where |
| 00:46:55 | <Inst> | then show Foo, at least in ghci, you hang |
| 00:47:00 | <Inst> | not even an exception |
| 00:47:19 | <jumper> | can Haskell be expressed through Python? |
| 00:47:22 | → | lisbeths joins (uid135845@id-135845.lymington.irccloud.com) |
| 00:47:25 | <geekosaur> | no |
| 00:47:29 | <jumper> | damn |
| 00:47:41 | <geekosaur> | or at least no more usefully than it can through C |
| 00:47:55 | <Inst> | wait, can typeclasses be expressed as C++ concepts? |
| 00:48:02 | <monochrom> | I translate Python to Haskell, for that subset of Python that is translatable to Haskell. |
| 00:48:03 | <Inst> | are you familiar with that? |
| 00:48:16 | <monochrom> | For the rest of Python, I just call it garbage and ignore. >:) |
| 00:48:54 | <geekosaur> | I'm not, I stopped bothering with C++ before they added concepts. Supposedly there are similarities though |
| 00:49:19 | <Inst> | https://en.cppreference.com/w/cpp/language/constraints |
| 00:49:21 | <Inst> | oh hey |
| 00:49:24 | <Inst> | this looks awfully familiar |
| 00:49:44 | <jumper> | C++11 please |
| 00:49:54 | <jumper> | D: |
| 00:50:28 | <Inst> | how about, let's leave it this way, Haskell has a really powerful type system, typeclasses, constraints, and => are part of Haskell's really powerful type system |
| 00:51:26 | <monochrom> | Inst: And if you "instance Eq Foo", then "Foo == Foo" also hangs. Do you now see why? |
| 00:51:26 | <Inst> | If you are really desperate, imo, I took a look at monochrom's lecture notes. Those are really good, and get to typeclasses really fast. |
| 00:52:05 | <Inst> | I don't, actually. The point is more, there's no implementation for either show or (==) |
| 00:52:13 | <Inst> | I'd have expected Haskell to throw an exception |
| 00:52:20 | <monochrom> | But there are default implementations. That's why. |
| 00:52:25 | <Inst> | ahhh |
| 00:52:27 | <Inst> | doip |
| 00:52:40 | <monochrom> | And there are static warnings. |
| 00:52:42 | <jrm> | Hi. I'm very new to Haskell and just at the 'playing around' stage, i.e., I have no clue what I'm doing. I just tested calculating a Fibonacci sequence with n=45 using C and Haskell. https://paste.tomsmeding.com/E9GhyxAC https://paste.tomsmeding.com/b5Tz9Pfa. On my laptop, the C program took 12.7 s and the Haskell program took 110 s to complete. Surely I must be doing something wrong for the Haskell program to take ~9 times longer. |
| 00:53:33 | <geekosaur> | I thought == lost its default when /= left the typeclass, because the default was in terms of /= |
| 00:54:28 | <monochrom> | Ah now I think I've heard that, but too recent. |
| 00:54:48 | <geekosaur> | jrm, you're doing it the slow way so it has to keep recalculating things. Haskell does not memoize automatically |
| 00:54:49 | <monochrom> | Was it in 9.4? I happen to have a 9.4 docker image... |
| 00:54:57 | <geekosaur> | I think so? |
| 00:55:05 | <Inst> | wait, is there a space leak there? |
| 00:55:43 | <Inst> | i mean Haskell taking 9 times longer suggests there's a space leak |
| 00:56:05 | <Inst> | geekosaur: the C program is also essentially the same algorithm and probably stack overflows for n=46 or something |
| 00:56:06 | <monochrom> | /= is still part of Eq in 9.4. I'll try 9.6. |
| 00:56:19 | × | Lord_of_Life quits (~Lord@user/lord-of-life/x-2819915) (Ping timeout: 245 seconds) |
| 00:56:47 | <Inst> | i'm more interested in the haskell program insofar as you'd want to ask how to get it not to space leak |
| 00:57:01 | <geekosaur> | yeh, just found that (sadly the docs went weird starting with 9.4) |
| 00:57:04 | → | Lord_of_Life joins (~Lord@user/lord-of-life/x-2819915) |
| 00:57:29 | <geekosaur> | it only suggests a time leak, not necessarily a space leak 🙂 |
| 00:58:07 | <monochrom> | I had the 9.6 docker image but I deleted it to save disk space. I should steal more space from my unused Windows partition... |
| 00:58:23 | <geekosaur> | anyway it goes faster if you use a definition that memoizes instead of constantly recalculating (which will be slow, Haskell is not an especially fast language when it comes to brute-force computation) |
| 00:58:26 | <monochrom> | Hrm no change in 9.6. |
| 00:58:44 | <monochrom> | But yeah I think I heard that one day /= will be moving out... |
| 00:59:01 | <monochrom> | But really I'm still with 9.2 :) |
| 00:59:33 | <monochrom> | But OK, I see that ghcup is now recommending 9.4, I will migrate soon. |
| 00:59:57 | <monochrom> | But the C version is doing the same non-tail exponential recursion. |
| 01:00:10 | <geekosaur> | yes, the comment about brute force applies more |
| 01:00:14 | <monochrom> | I think I should first ask/remind "did you tell GHC to -O?" |
| 01:00:22 | <geekosaur> | memoization is how you defeat it 🙂 |
| 01:00:50 | <geekosaur> | anyway: the way to speed this up is to memoize in some way or another, either caching in a Map or being clever |
| 01:00:59 | <monochrom> | But if someone points out "gcc changes it to memoization" I wouldn't be surprised. :) |
| 01:01:42 | <geekosaur> | @let fibs = 0 : 1 : zipWith (+) fibs (tail fibs) |
| 01:01:43 | <lambdabot> | Defined. |
| 01:02:36 | <monochrom> | Some years ago someone wrote "for i from 1 to N" and furiously complained that Haskell was slow. Turned out gcc cheated and compiled that loop to one single O(1) assignment i=N. |
| 01:02:42 | <jrm> | This Fibonacci example is in Chapter 6 of 'Programming in Haskell', 2nd Ed. by Graham Hutton. |
| 01:02:57 | <Inst> | that probably was me |
| 01:03:01 | <jrm> | To be clear, I'm not complaining. Just curious. :) |
| 01:03:03 | <geekosaur> | > fibs !! 45 -- hm, did I add one too many? |
| 01:03:03 | <Inst> | since I've done dumb crap like that |
| 01:03:04 | <lambdabot> | 1134903170 |
| 01:03:14 | <geekosaur> | nope, that's it |
| 01:03:38 | <geekosaur> | and not even with optimization |
| 01:04:08 | <Inst> | no, but jrm's problem is actually interesting |
| 01:04:13 | <Inst> | it's not "this is the wrong fib algorithm" |
| 01:04:20 | <Inst> | it's more "why is this algorithm space leaking?" |
| 01:04:29 | <monochrom> | Decades ago I joked about "one day, the compiler is so smart, if you write bubble sort, the compiler will go 'I see you're sorting' and replace it with an actually good sorting algorithm, now you have trouble showing students empirical proof that bubble sort takes quadratic time". |
| 01:04:55 | <monochrom> | It is "comforting" to know that we are really getting closer to that dystopia. |
| 01:05:21 | <jumper> | Does Haskell have anything similar to "Perldoc" or "Pydoc"? |
| 01:05:28 | <geekosaur> | no, it's just recomputing the same things over and over. this is not a space leak |
| 01:05:36 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) |
| 01:05:37 | <geekosaur> | show me the space leak if you are so certain it has one |
| 01:05:44 | <geekosaur> | jumper: haddock |
| 01:05:52 | <jumper> | geekosaur, thanks |
| 01:05:59 | → | brandly joins (~brandly@c-73-68-15-46.hsd1.ma.comcast.net) |
| 01:06:23 | <Inst> | geekosaur: it's just the numbers that seem weird, naive bad algorithm in C should be only 2-5 times faster than a naive bad algorithm in Haskell |
| 01:07:05 | <jrm> | geekosaur: Wow, your implementation is blazing fast. |
| 01:07:30 | <Inst> | iirc, there are faster implementations, no? |
| 01:07:33 | <monochrom> | You know, I expect the Haskell version to use 4 times as much memory as the C version. |
| 01:07:50 | <monochrom> | 1. C int is half of Haskell Int. 32 bits vs 64 bits |
| 01:07:52 | <geekosaur> | sure, it's memoizing it since it's a top level definition with no parameters |
| 01:08:03 | <monochrom> | 2. Copying GC implies double buffering. |
| 01:08:18 | <geekosaur> | there is --nonmoving-gc |
| 01:09:21 | <geekosaur> | both your C and Haskell implementations repeatedly recalculate values. Haskell will always lose at that kind of brute force approach |
| 01:10:41 | <geekosaur> | the memoizing version computes each one once and remembers it instead of recomputing it, so it uses more space but is very fast |
| 01:11:36 | <Inst> | hmmm, i forget what the ratio is between the Haskell caching version and the C caching version |
| 01:11:53 | <monochrom> | This becomes a problem with benchmarking, especially standardized benchmarking. |
| 01:12:32 | <monochrom> | You probably write a deliberately brute-forcing or at least somewhat-dumb algorithm in hope of benchmarking. |
| 01:12:55 | × | billchenchina quits (~billchenc@2a0d:2580:ff0c:1:e3c9:c52b:a429:5bfe) (Remote host closed the connection) |
| 01:13:19 | <monochrom> | But commercial compilers have done "I see that your code is literally SPEC94 so I'm going to go ahead and cheat and just emit a O(1) x=finalAnswer instruction". |
| 01:14:12 | <Inst> | do people actually do this in Haskell? |
| 01:14:14 | <Inst> | https://www.nayuki.io/page/karatsuba-multiplication |
| 01:14:40 | <jumper> | are there Haskell newsgroups one could follow? |
| 01:15:04 | <monochrom> | Newsgroups! comp.lang.haskell exists actually. |
| 01:15:26 | <monochrom> | Hell, was created right at the time people left newsgroups in general haha |
| 01:15:54 | × | waleee quits (~waleee@h-176-10-137-138.NA.cust.bahnhof.se) (Ping timeout: 245 seconds) |
| 01:15:59 | <Inst> | Ummm, that's dead :( |
| 01:16:17 | <Inst> | from what I can tell, the most lively Haskell community left is discourse.haskell.org |
| 01:17:10 | <monochrom> | GHC uses GMP. GMP takes a look at the input size and chooses the right algorithm. |
| 01:17:17 | <monochrom> | for multiplication |
| 01:17:57 | <Inst> | wasn't there an attempt to replace gmp by native? |
| 01:18:06 | <monochrom> | On top of that, GHC takes a look at the number size and chooses between staying Int64 or using GMP. |
| 01:18:20 | <monochrom> | "It's telephone games all the way down" |
| 01:19:44 | → | \salt joins (~salt@cpe-172-248-205-14.socal.res.rr.com) |
| 01:19:53 | ← | \salt parts (~salt@cpe-172-248-205-14.socal.res.rr.com) () |
| 01:21:19 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) (Remote host closed the connection) |
| 01:21:30 | <geekosaur> | not an attempt, native mode has always existed, it's just slower than GMP. but there are commercial GHC users who won't touch GPL or LGPL, so they use the native backend |
| 01:21:34 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) |
| 01:21:49 | <yin> | monochrom: js's "fat arrow" lambdas *slightly* differ from anonymous functions of the style "function (x) { ..." |
| 01:21:57 | <geekosaur> | there was a recent rewrite that makes native significantly faster for everything except large multiplications iirc |
| 01:22:17 | <monochrom> | What is the difference? |
| 01:22:28 | <geekosaur> | ditched lists in favor of something sensible |
| 01:22:49 | <monochrom> | Err I mean for yin about JS function syntaxes :) |
| 01:22:57 | <geekosaur> | oh |
| 01:23:09 | <monochrom> | But yeah list is terrible :) |
| 01:23:27 | <geekosaur> | I still want to revive the old attempt at using libtommath (BSD license) as a backend, since it's been a good 15 years and I expect it to have improved |
| 01:23:54 | <yin> | monochrom: lexical scoping |
| 01:24:49 | <yin> | you can't create a closure with fat arrow |
| 01:25:12 | → | Vajb joins (~Vajb@207.61.167.122) |
| 01:25:33 | <yin> | i mean, you can |
| 01:25:39 | <yin> | but not in the same way |
| 01:25:47 | <jumper> | what's the >>== operator called? |
| 01:25:53 | <geekosaur> | "bind" |
| 01:25:54 | <monochrom> | bind |
| 01:25:55 | <yin> | "bind" |
| 01:27:44 | <EvanR> | >>= |
| 01:28:38 | <EvanR> | and what is the >> operator called |
| 01:30:24 | <jackdk> | "*>" |
| 01:30:28 | <monochrom> | "then" :) |
| 01:30:54 | <monochrom> | But far fewer people ask for names for >> or *> |
| 01:30:58 | <EvanR> | what about << |
| 01:31:16 | <[Leary]> | "neht" |
| 01:31:29 | <monochrom> | People who actually don't mind using << have learned to not name operators. :) |
| 01:31:52 | <Inst> | << is also freaky, do you know why? |
| 01:32:02 | <EvanR> | skeptical, but why |
| 01:32:06 | <monochrom> | It is generally just beginners and COBOL people who insist on translating Haskell to English. |
| 01:32:17 | <monochrom> | I guess s/COBOL/COBOL-minded/ |
| 01:32:26 | × | _xor quits (~xor@72.49.199.93) (Ping timeout: 255 seconds) |
| 01:32:52 | <monochrom> | Most programmers haven't even heard of COBOL, but make no mistake, they just didn't know they would love it. |
| 01:33:24 | <Inst> | first of all, it doesn't actually exist |
| 01:33:28 | <yin> | i wish i had learned lisp before learning haskell |
| 01:33:35 | <EvanR> | << doesn't actually exist? |
| 01:33:50 | <monochrom> | Judging from how the OOP extremists I mentioned would even reject "o2.m2(o1.m1())" and insist to write like "tmp = o1.m1(); o2.m2(tmp)". |
| 01:33:59 | <Inst> | https://hoogle.haskell.org/?hoogle=%3C%3C |
| 01:34:08 | <geekosaur> | there's the old joke that an OO COBOL would have been called ADD 1 TO COBOL GIVING COBOL |
| 01:34:16 | <monochrom> | haha |
| 01:34:42 | <geekosaur> | (which is actually redundant) |
| 01:34:49 | <Inst> | but <* is still freaky |
| 01:35:07 | <Inst> | putStr "Hello" <* putStr " World" |
| 01:35:32 | <jumper> | monochrom, why, I'd rather nest that write repetitive code |
| 01:35:37 | <jumper> | than* |
| 01:35:44 | → | _xor joins (~xor@72.49.199.93) |
| 01:35:52 | <jackdk> | Inst: that did exactly what I expected it to do? |
| 01:35:54 | × | zenstoic quits (uid461840@id-461840.hampstead.irccloud.com) (Quit: Connection closed for inactivity) |
| 01:36:00 | <geekosaur> | don't confuse results and effects |
| 01:36:14 | <monochrom> | "o2.m2(o1.m1())" looks dangerouly close to FP and/or math. |
| 01:36:25 | <monochrom> | You know that most programmers hate math, right? |
| 01:36:39 | <jumper> | nah |
| 01:36:41 | <Inst> | no, but you'd expect there to be a flip (>>) somewhere, no? |
| 01:37:16 | <EvanR> | I guess by the time =<< was catching on Monad had already been sort of upstaged by Applicative |
| 01:37:39 | <monochrom> | It is the only reason why Haskell beginners ask "how do I get rid of parentheses in f (g (x + 1))" |
| 01:37:41 | <EvanR> | and the AMP update |
| 01:38:01 | <yin> | :t Control.Arrow.<<^ |
| 01:38:02 | <lambdabot> | error: parse error on input ‘Control.Arrow.<<^’ |
| 01:38:04 | <geekosaur> | there was never really a call for it |
| 01:38:11 | <yin> | :t Control.Arrow.(<<^) |
| 01:38:12 | <lambdabot> | error: |
| 01:38:12 | <lambdabot> | Not in scope: data constructor ‘Control.Arrow’ |
| 01:38:12 | <lambdabot> | No module named ‘Control’ is imported. |
| 01:38:22 | <yin> | welp |
| 01:38:34 | <geekosaur> | :t (Control.Arrow.<<^) |
| 01:38:35 | <lambdabot> | Arrow a => a c d -> (b -> c) -> a b d |
| 01:38:44 | <jumper> | how close is Haskell's syntax to pure mathematic syntax? Is APL closer? |
| 01:38:47 | × | otto_s quits (~user@p5de2f3ed.dip0.t-ipconnect.de) (Ping timeout: 260 seconds) |
| 01:39:02 | <yin> | APL is nowhere near? |
| 01:39:16 | <geekosaur> | APL is much closer, but different areas of math often have different syntax and APL's staked out matrix math |
| 01:39:18 | <EvanR> | APL and math have in common very dense syntax |
| 01:39:34 | <EvanR> | so maybe the question is about density |
| 01:39:40 | <yin> | what is "pure math syntax"? |
| 01:39:55 | <monochrom> | I am more interested in: Haskell semantics is closer to math semantics. |
| 01:40:07 | <geekosaur> | nonsensical. every area of math has its own syntax |
| 01:40:16 | → | otto_s joins (~user@p5de2fd40.dip0.t-ipconnect.de) |
| 01:40:37 | <EvanR> | if you don't have bottom, the semantics IS math |
| 01:40:56 | <geekosaur> | math can describe bottom |
| 01:40:57 | <EvanR> | the denotation of function type are math functions |
| 01:41:31 | <geekosaur> | the forms of math usually used with Haskell can't |
| 01:42:06 | <geekosaur> | I don't recall what you have to do to CT to make Hask (the "category" of Haskell types) meaningful |
| 01:42:25 | <geekosaur> | …in the presence of bottom |
| 01:43:04 | <yin> | can't any code that can produce an AST which can be interpreted considered a type of "math syntax"? |
| 01:43:11 | <geekosaur> | (noting "Fast and Loose Reasoning is Morally Correct") |
| 01:43:47 | <EvanR> | another adjustment to jumper's question is: if the meaning of lambdas-in-lambda-calculus is "functions" what is the domain and range of the functions |
| 01:44:21 | <geekosaur> | nonexistent in the untyped lambda calculus |
| 01:44:38 | <geekosaur> | STLC, now you can discuss them I think |
| 01:44:44 | <EvanR> | untyped can also mean "one master type" |
| 01:45:01 | <yin> | unotyped |
| 01:45:16 | <monochrom> | Yeah I go with "one master type" in the case of untyped lambda calculus. |
| 01:45:40 | <monochrom> | And it doesn't have to mean "the object language has syntax for referring to that master type". |
| 01:47:35 | <monochrom> | The object language doesn't let you talk about domains and codomains. But when you want to know about semantics, i.e., at the meta level, then you need to talk about it |
| 01:48:26 | <monochrom> | It did take almost forever for Dana Scott et. al to prove that the master type actually exists in the math sense! |
| 01:50:30 | × | talismanick quits (~user@2601:204:ef80:2980::b23e) (Ping timeout: 272 seconds) |
| 01:53:05 | <jumper> | outside from haskell, are there any communities one could participate in, if one is interested in automata theory, philosophy and literature intermixed with math? |
| 01:56:12 | × | Inst quits (~Inst@120.244.192.250) (Ping timeout: 272 seconds) |
| 02:01:36 | <yin> | #math maybe? |
| 02:04:15 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Killed (NickServ (Forcing logout FinnElija -> finn_elija))) |
| 02:04:15 | → | finn_elija joins (~finn_elij@user/finn-elija/x-0085643) |
| 02:04:15 | finn_elija | is now known as FinnElija |
| 02:07:27 | × | Vajb quits (~Vajb@207.61.167.122) (Ping timeout: 240 seconds) |
| 02:10:22 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 255 seconds) |
| 02:26:44 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 02:29:36 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 02:32:55 | × | Square quits (~Square@user/square) (Remote host closed the connection) |
| 02:33:19 | → | Lestat9 joins (~Admin1@47.200.90.216) |
| 02:33:35 | <lisbeths> | monochrom: with syntax macros you can extend the grammar syntax or semantics of a language to any possible syntax that you can imagine |
| 02:34:40 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 255 seconds) |
| 02:40:02 | <lisbeths> | monochrom: typed lambda calculus is more similar to math because it is conistent rather than complete |
| 02:40:38 | <lisbeths> | sets can be implemented in untyped lambda calculus and sets can be implemented in typed lambda calculus |
| 02:41:36 | <EvanR> | Data.Sets? |
| 02:41:54 | <lisbeths> | zermelo frankl sets. any kind of sets |
| 02:42:09 | <EvanR> | how does that work |
| 02:42:37 | <lisbeths> | Anything which is mathematically complete has a subset which is an implementation of sets |
| 02:43:26 | × | srk quits (~sorki@user/srk) (Remote host closed the connection) |
| 02:43:44 | → | srk joins (~sorki@user/srk) |
| 02:51:50 | × | Lestat9 quits (~Admin1@47.200.90.216) (Quit: Leaving) |
| 02:53:25 | × | bilegeek quits (~bilegeek@2600:1008:b02f:1011:22e7:78e8:8a34:1aa8) (Quit: Leaving) |
| 02:54:04 | → | jimmy joins (~jimmy@82.sub-174-215-177.myvzw.com) |
| 02:57:40 | × | sabino quits (~sabino@user/sabino) (Quit: Lambda _ -> x) |
| 02:58:01 | × | td_ quits (~td@i53870930.versanet.de) (Ping timeout: 260 seconds) |
| 02:59:39 | → | td_ joins (~td@i53870923.versanet.de) |
| 02:59:51 | × | machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 260 seconds) |
| 03:02:32 | <EvanR> | so in the early days of trying to found mathematics using lambda calculus, one obvious test drive is to encode sets. It failed, so they just went with sets directly? xD (curry's paradox, or other logical flaw in ULC) |
| 03:03:11 | → | Square joins (~Square@user/square) |
| 03:06:15 | × | cyphase quits (~cyphase@user/cyphase) (Ping timeout: 240 seconds) |
| 03:07:21 | → | smalltalkman joins (uid545680@id-545680.hampstead.irccloud.com) |
| 03:10:43 | → | aforemny_ joins (~aforemny@i59F516EC.versanet.de) |
| 03:11:20 | × | aforemny quits (~aforemny@2001:9e8:6ce4:3000:fb34:5497:c705:b99) (Ping timeout: 255 seconds) |
| 03:11:24 | → | Allak joins (~Admin1@47.200.90.216) |
| 03:12:23 | → | cyphase joins (~cyphase@user/cyphase) |
| 03:16:51 | × | img quits (~img@user/img) (Quit: ZNC 1.8.2 - https://znc.in) |
| 03:17:21 | → | img joins (~img@user/img) |
| 03:18:59 | × | img quits (~img@user/img) (Client Quit) |
| 03:19:54 | → | img joins (~img@user/img) |
| 03:22:50 | × | ddellacosta quits (~ddellacos@ool-44c738de.dyn.optonline.net) (Ping timeout: 246 seconds) |
| 03:23:22 | × | Allak quits (~Admin1@47.200.90.216) (Remote host closed the connection) |
| 03:27:55 | <lisbeths> | I think the reason why it failed is that it is inconsistent, EvanR |
| 03:34:17 | <lisbeths> | you can use untyped lambda calculus to implement typed lambda calculus |
| 03:36:42 | × | alphacentauri quits (alphacenta@gateway/vpn/protonvpn/alphacentauri) (Quit: WeeChat 4.0.5) |
| 03:44:39 | × | Square quits (~Square@user/square) (Quit: Leaving) |
| 03:44:43 | → | pavonia joins (~user@user/siracusa) |
| 03:45:59 | → | Square joins (~Square@user/square) |
| 03:49:11 | × | jumper quits (~jumper@mobile-access-2e844c-234.dhcp.inet.fi) (Quit: leaving) |
| 03:51:16 | → | Unicorn_Princess joins (~Unicorn_P@user/Unicorn-Princess/x-3540542) |
| 03:58:46 | → | alphacentauri joins (alphacenta@gateway/vpn/protonvpn/alphacentauri) |
| 04:01:50 | × | megaTherion quits (~therion@unix.io) (Quit: ZNC 1.8.2 - https://znc.in) |
| 04:02:15 | → | actioninja joins (~actioninj@user/actioninja) |
| 04:03:49 | → | megaTherion joins (~therion@unix.io) |
| 04:05:06 | × | dcoutts quits (~duncan@host86-146-194-46.range86-146.btcentralplus.com) (Ping timeout: 260 seconds) |
| 04:06:01 | → | _ht joins (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) |
| 04:11:58 | × | jimmy quits (~jimmy@82.sub-174-215-177.myvzw.com) (Quit: Quit) |
| 04:21:07 | × | Square quits (~Square@user/square) (Remote host closed the connection) |
| 04:22:05 | → | qhong_ joins (~qhong@rescomp-21-400677.stanford.edu) |
| 04:24:15 | × | qhong quits (~qhong@rescomp-21-400677.stanford.edu) (Ping timeout: 240 seconds) |
| 04:25:04 | → | Square joins (~Square@user/square) |
| 04:25:36 | × | megaTherion quits (~therion@unix.io) (Ping timeout: 260 seconds) |
| 04:25:53 | → | megaTherion joins (~therion@unix.io) |
| 04:26:18 | × | flocks quits (~flocks@134.122.90.60) (Ping timeout: 272 seconds) |
| 04:26:40 | → | srk_ joins (~sorki@user/srk) |
| 04:26:56 | × | srk quits (~sorki@user/srk) (Ping timeout: 272 seconds) |
| 04:27:18 | → | orcus- joins (~orcus@mail.brprice.uk) |
| 04:27:56 | → | flocks joins (~flocks@134.122.90.60) |
| 04:28:12 | × | quintasan quits (~quassel@quintasan.pl) (Ping timeout: 272 seconds) |
| 04:28:12 | × | Dykam quits (Dykam@dykam.nl) (Ping timeout: 272 seconds) |
| 04:28:12 | × | orcus quits (~orcus@mail.brprice.uk) (Ping timeout: 272 seconds) |
| 04:28:13 | → | quintasan_ joins (~quassel@quintasan.pl) |
| 04:28:23 | × | kantokuen quits (~kantokuen@user/kantokuen) (Quit: leaving) |
| 04:28:43 | → | Dykam joins (Dykam@dykam.nl) |
| 04:29:26 | srk_ | is now known as srk |
| 04:39:04 | → | michalz joins (~michalz@185.246.207.222) |
| 04:43:52 | → | dcoutts joins (~duncan@185.201.63.254) |
| 04:46:36 | → | kantokuen joins (~kantokuen@user/kantokuen) |
| 04:46:44 | × | brandly quits (~brandly@c-73-68-15-46.hsd1.ma.comcast.net) (Ping timeout: 255 seconds) |
| 04:47:48 | × | dcoutts quits (~duncan@185.201.63.254) (Remote host closed the connection) |
| 04:48:08 | → | dcoutts joins (~duncan@185.201.63.254) |
| 04:51:01 | × | L29Ah quits (~L29Ah@wikipedia/L29Ah) (Ping timeout: 255 seconds) |
| 05:09:22 | × | dcoutts quits (~duncan@185.201.63.254) (Ping timeout: 260 seconds) |
| 05:17:57 | → | takuan joins (~takuan@178-116-218-225.access.telenet.be) |
| 05:25:42 | → | Inst joins (~Inst@120.244.192.250) |
| 05:28:34 | × | [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Read error: Connection reset by peer) |
| 05:28:58 | → | Square3 joins (~Square4@user/square) |
| 05:31:44 | × | Square quits (~Square@user/square) (Ping timeout: 255 seconds) |
| 05:43:57 | × | _ht quits (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) (Quit: _ht) |
| 05:44:07 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 255 seconds) |
| 05:57:47 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 06:00:32 | → | acidjnk joins (~acidjnk@p200300d6e7072f57652bd3d039ad030c.dip0.t-ipconnect.de) |
| 06:01:03 | × | Inst quits (~Inst@120.244.192.250) (Remote host closed the connection) |
| 06:01:22 | → | Inst joins (~Inst@120.244.192.250) |
| 06:03:32 | → | misterfish joins (~misterfis@87.215.131.102) |
| 06:20:39 | × | Inst quits (~Inst@120.244.192.250) (Ping timeout: 246 seconds) |
| 06:21:20 | × | misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 246 seconds) |
| 06:21:47 | → | harveypwca joins (~harveypwc@2601:246:c280:6a90:837d:db39:3eea:f7db) |
| 06:26:22 | → | misterfish joins (~misterfis@g250100.upc-g.chello.nl) |
| 06:31:10 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 06:36:06 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 258 seconds) |
| 06:39:22 | → | lortabac joins (~lortabac@2a01:e0a:541:b8f0:990f:a737:63e:2e4a) |
| 06:39:23 | → | Inst joins (~Inst@120.244.192.250) |
| 06:47:15 | × | paddymahoney quits (~paddymaho@cpe883d24bcf597-cmbc4dfb741f80.cpe.net.cable.rogers.com) (Remote host closed the connection) |
| 06:48:10 | × | michalz quits (~michalz@185.246.207.222) (Ping timeout: 252 seconds) |
| 06:48:54 | → | idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) |
| 06:58:24 | → | michalz joins (~michalz@185.246.207.197) |
| 06:59:07 | × | Inst quits (~Inst@120.244.192.250) (Ping timeout: 264 seconds) |
| 07:06:24 | → | fendor joins (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) |
| 07:06:47 | × | zaquest quits (~notzaques@5.130.79.72) (Remote host closed the connection) |
| 07:16:34 | → | gmg joins (~user@user/gehmehgeh) |
| 07:24:14 | × | bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Remote host closed the connection) |
| 07:24:19 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Remote host closed the connection) |
| 07:24:46 | → | FinnElija joins (~finn_elij@user/finn-elija/x-0085643) |
| 07:25:15 | → | bitdex joins (~bitdex@gateway/tor-sasl/bitdex) |
| 07:26:33 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 07:27:05 | × | misterfish quits (~misterfis@g250100.upc-g.chello.nl) (Ping timeout: 258 seconds) |
| 07:27:19 | → | vglfr joins (~vglfr@88.155.159.184) |
| 07:31:21 | × | rgw quits (~R@2605:a601:a0df:5600:a4a0:a66c:3431:6e78) (Read error: Connection reset by peer) |
| 07:31:36 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 07:32:16 | → | vglfr joins (~vglfr@88.155.159.184) |
| 07:37:31 | <haskellbridge> | <tewuzij> How does syntax macro looks like? |
| 07:38:25 | <lisbeths> | binary lambda calculus is an example of a language that can be extended to arbitrary syntaxes |
| 07:41:26 | → | danza joins (~francesco@151.57.115.67) |
| 07:42:27 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 07:43:03 | → | vglfr joins (~vglfr@88.155.159.184) |
| 07:44:43 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 255 seconds) |
| 07:44:50 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) (Remote host closed the connection) |
| 07:45:29 | → | fweht joins (uid404746@id-404746.lymington.irccloud.com) |
| 07:46:44 | × | danza quits (~francesco@151.57.115.67) (Ping timeout: 255 seconds) |
| 07:47:53 | → | misterfish joins (~misterfis@87.215.131.102) |
| 07:47:55 | → | Pickchea joins (~private@user/pickchea) |
| 07:54:18 | → | machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net) |
| 07:55:13 | → | chele joins (~chele@user/chele) |
| 07:58:12 | × | fendor quits (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) (Remote host closed the connection) |
| 07:58:12 | → | fendor joins (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) |
| 07:58:12 | → | CiaoSen joins (~Jura@2a05:5800:2c0:1c00:664b:f0ff:fe37:9ef) |
| 07:58:34 | × | vglfr quits (~vglfr@88.155.159.184) (Ping timeout: 252 seconds) |
| 07:59:07 | × | azimut quits (~azimut@gateway/tor-sasl/azimut) (Ping timeout: 252 seconds) |
| 07:59:51 | × | califax quits (~califax@user/califx) (Ping timeout: 252 seconds) |
| 07:59:51 | × | ec quits (~ec@gateway/tor-sasl/ec) (Ping timeout: 252 seconds) |
| 07:59:51 | × | stiell_ quits (~stiell@gateway/tor-sasl/stiell) (Ping timeout: 252 seconds) |
| 08:00:35 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Ping timeout: 252 seconds) |
| 08:00:35 | × | gmg quits (~user@user/gehmehgeh) (Ping timeout: 252 seconds) |
| 08:00:35 | × | chexum quits (~quassel@gateway/tor-sasl/chexum) (Ping timeout: 252 seconds) |
| 08:00:35 | × | ChaiTRex quits (~ChaiTRex@user/chaitrex) (Ping timeout: 252 seconds) |
| 08:01:03 | → | vglfr joins (~vglfr@88.155.159.184) |
| 08:01:29 | × | harveypwca quits (~harveypwc@2601:246:c280:6a90:837d:db39:3eea:f7db) (Quit: Leaving) |
| 08:02:42 | × | Sgeo quits (~Sgeo@user/sgeo) (Read error: Connection reset by peer) |
| 08:03:35 | aforemny_ | is now known as aforemny |
| 08:03:49 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 08:04:52 | → | paddymahoney joins (~paddymaho@cpe883d24bcf597-cmbc4dfb741f80.cpe.net.cable.rogers.com) |
| 08:05:43 | → | Inst joins (~Inst@120.244.192.250) |
| 08:06:37 | → | Square2 joins (~Square4@user/square) |
| 08:08:35 | × | Square3 quits (~Square4@user/square) (Ping timeout: 240 seconds) |
| 08:08:37 | → | stiell_ joins (~stiell@gateway/tor-sasl/stiell) |
| 08:08:43 | → | chexum joins (~quassel@gateway/tor-sasl/chexum) |
| 08:09:10 | → | califax joins (~califax@user/califx) |
| 08:09:11 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 08:09:38 | → | FinnElija joins (~finn_elij@user/finn-elija/x-0085643) |
| 08:09:40 | → | azimut joins (~azimut@gateway/tor-sasl/azimut) |
| 08:10:42 | → | ChaiTRex joins (~ChaiTRex@user/chaitrex) |
| 08:11:06 | → | gehmehgeh joins (~user@user/gehmehgeh) |
| 08:12:07 | kantokuen | is now known as kanto |
| 08:12:23 | × | patrl quits (~patrl@user/patrl) (Ping timeout: 255 seconds) |
| 08:12:23 | × | tomsmeding quits (~tomsmedin@2a01:4f8:c0c:5e5e::2) (Ping timeout: 255 seconds) |
| 08:12:23 | × | mcfrdy quits (~mcfrdy@user/mcfrdy) (Ping timeout: 255 seconds) |
| 08:12:38 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 246 seconds) |
| 08:12:43 | → | tomsmeding joins (~tomsmedin@2a01:4f8:c0c:5e5e::2) |
| 08:12:43 | → | mcfrdy joins (~mcfrdy@user/mcfrdy) |
| 08:13:17 | × | dyniec quits (~dyniec@mail.dybiec.info) (Ping timeout: 255 seconds) |
| 08:13:17 | × | V quits (~v@ircpuzzles/2022/april/winner/V) (Ping timeout: 255 seconds) |
| 08:13:17 | × | mht-wtf quits (~mht@2a03:b0c0:3:e0::1e2:c001) (Ping timeout: 255 seconds) |
| 08:13:17 | × | kawzeg_ quits (kawzeg@2a01:7e01::f03c:92ff:fee2:ec34) (Ping timeout: 255 seconds) |
| 08:13:44 | × | yahb2 quits (~yahb2@2a01:4f8:c0c:5c7b::2) (Ping timeout: 255 seconds) |
| 08:13:57 | → | V joins (~v@ircpuzzles/2022/april/winner/V) |
| 08:14:21 | → | patrl joins (~patrl@user/patrl) |
| 08:14:56 | → | dyniec joins (~dyniec@mail.dybiec.info) |
| 08:15:05 | → | kawzeg_ joins (kawzeg@2a01:7e01::f03c:92ff:fee2:ec34) |
| 08:15:14 | → | yahb2 joins (~yahb2@2a01:4f8:c0c:5c7b::2) |
| 08:15:14 | ChanServ | sets mode +v yahb2 |
| 08:15:14 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 08:16:25 | × | califax quits (~califax@user/califx) (Remote host closed the connection) |
| 08:16:42 | → | califax joins (~califax@user/califx) |
| 08:17:04 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) |
| 08:18:37 | → | mht-wtf joins (~mht@2a03:b0c0:3:e0::1e2:c001) |
| 08:19:15 | × | Pickchea quits (~private@user/pickchea) (Quit: Leaving) |
| 08:21:32 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) (Ping timeout: 248 seconds) |
| 08:25:20 | → | danse-nr3 joins (~francesco@151.57.115.67) |
| 08:30:50 | → | Guest61 joins (~Guest34@194.61.40.138) |
| 08:32:10 | × | tzh quits (~tzh@c-71-193-181-0.hsd1.or.comcast.net) (Quit: zzz) |
| 08:35:23 | → | xdej joins (~xdej@quatramaran.salle-s.org) |
| 08:45:17 | × | idgaen quits (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) (Quit: WeeChat 4.0.5) |
| 08:49:48 | × | chele quits (~chele@user/chele) (Ping timeout: 240 seconds) |
| 08:50:53 | → | kuribas joins (~user@ip-188-118-57-242.reverse.destiny.be) |
| 08:56:26 | → | Jackneill joins (~Jackneill@20014C4E1E021C00C8911A68759FC1A4.dsl.pool.telekom.hu) |
| 09:02:25 | → | __monty__ joins (~toonn@user/toonn) |
| 09:02:28 | → | chele joins (~chele@user/chele) |
| 09:03:27 | → | cpressey joins (~cpressey@host-92-21-195-194.as13285.net) |
| 09:04:13 | → | Sanguine_ joins (~Sanguine@176.254.244.83) |
| 09:06:56 | × | Sanguine quits (~Sanguine@176.254.244.83) (Ping timeout: 255 seconds) |
| 09:10:32 | → | chele_ joins (~chele@user/chele) |
| 09:11:53 | × | chele quits (~chele@user/chele) (Ping timeout: 255 seconds) |
| 09:18:19 | × | azimut quits (~azimut@gateway/tor-sasl/azimut) (Ping timeout: 252 seconds) |
| 09:20:02 | × | gehmehgeh quits (~user@user/gehmehgeh) (Quit: Leaving) |
| 09:20:40 | → | rawles joins (~rawles@user/rawles) |
| 09:22:44 | → | wootehfoot joins (~wootehfoo@user/wootehfoot) |
| 09:24:14 | × | Guest61 quits (~Guest34@194.61.40.138) (Quit: Client closed) |
| 09:26:29 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) |
| 09:28:53 | × | ft quits (~ft@p3e9bc680.dip0.t-ipconnect.de) (Quit: leaving) |
| 09:34:34 | × | shapr quits (~user@2600:1700:c640:3100:bfe1:f742:1b66:58fa) (Remote host closed the connection) |
| 09:34:47 | → | shapr joins (~user@2600:1700:c640:3100:e051:bcd9:9086:b34f) |
| 09:51:41 | × | Inst quits (~Inst@120.244.192.250) (Ping timeout: 246 seconds) |
| 09:59:52 | → | Inst joins (~Inst@120.244.192.250) |
| 10:13:07 | × | econo_ quits (uid147250@id-147250.tinside.irccloud.com) (Quit: Connection closed for inactivity) |
| 10:15:29 | × | CiaoSen quits (~Jura@2a05:5800:2c0:1c00:664b:f0ff:fe37:9ef) (Ping timeout: 246 seconds) |
| 10:15:33 | × | fendor quits (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) (Remote host closed the connection) |
| 10:19:54 | → | finn_elija joins (~finn_elij@user/finn-elija/x-0085643) |
| 10:19:54 | × | FinnElija quits (~finn_elij@user/finn-elija/x-0085643) (Killed (NickServ (Forcing logout FinnElija -> finn_elija))) |
| 10:19:54 | finn_elija | is now known as FinnElija |
| 10:21:26 | × | lisbeths quits (uid135845@id-135845.lymington.irccloud.com) (Quit: Connection closed for inactivity) |
| 10:26:58 | → | Nixkernal_ joins (~Nixkernal@115.16.194.178.dynamic.wline.res.cust.swisscom.ch) |
| 10:27:52 | × | Nixkernal quits (~Nixkernal@115.16.194.178.dynamic.wline.res.cust.swisscom.ch) (Ping timeout: 260 seconds) |
| 10:30:05 | × | misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 255 seconds) |
| 10:31:55 | → | misterfish joins (~misterfis@178.228.26.213) |
| 10:32:42 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 10:36:58 | × | alphacentauri quits (alphacenta@gateway/vpn/protonvpn/alphacentauri) (Quit: WeeChat 4.0.5) |
| 10:38:04 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 272 seconds) |
| 11:02:21 | → | moni_ joins (~moni@cpe-174-106-185-141.ec.res.rr.com) |
| 11:05:16 | → | mikoto-chan joins (~mikoto-ch@ip-212-239-236-59.dsl.scarlet.be) |
| 11:16:13 | × | Inst quits (~Inst@120.244.192.250) (Quit: Leaving) |
| 11:16:35 | × | moni_ quits (~moni@cpe-174-106-185-141.ec.res.rr.com) (Ping timeout: 240 seconds) |
| 11:20:10 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 11:21:07 | → | vglfr joins (~vglfr@88.155.159.184) |
| 11:21:36 | → | cfricke joins (~cfricke@user/cfricke) |
| 11:24:15 | → | moni_ joins (~moni@cpe-174-106-185-141.ec.res.rr.com) |
| 11:24:31 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 11:25:22 | → | vglfr joins (~vglfr@88.155.159.184) |
| 11:25:59 | × | danse-nr3 quits (~francesco@151.57.115.67) (Ping timeout: 255 seconds) |
| 11:26:35 | × | mikoto-chan quits (~mikoto-ch@ip-212-239-236-59.dsl.scarlet.be) (Ping timeout: 240 seconds) |
| 11:28:33 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 11:29:43 | → | vglfr joins (~vglfr@88.155.159.184) |
| 11:30:45 | chele_ | is now known as chele |
| 11:40:43 | × | ec quits (~ec@gateway/tor-sasl/ec) (Read error: Connection reset by peer) |
| 11:40:43 | × | bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Read error: Connection reset by peer) |
| 11:40:43 | × | ChaiTRex quits (~ChaiTRex@user/chaitrex) (Read error: Connection reset by peer) |
| 11:41:07 | → | ec joins (~ec@gateway/tor-sasl/ec) |
| 11:41:11 | → | ChaiTRex joins (~ChaiTRex@user/chaitrex) |
| 11:41:39 | → | bitdex joins (~bitdex@gateway/tor-sasl/bitdex) |
| 11:42:28 | × | pandeyan quits (~pandeyan@135-180-55-136.fiber.dynamic.sonic.net) (Quit: ZNC 1.8.2 - https://znc.in) |
| 11:44:27 | → | anpad joins (~pandeyan@user/anpad) |
| 11:44:43 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 11:47:56 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 248 seconds) |
| 11:50:01 | × | misterfish quits (~misterfis@178.228.26.213) (Ping timeout: 260 seconds) |
| 11:54:42 | × | bitdex quits (~bitdex@gateway/tor-sasl/bitdex) (Quit: = "") |
| 11:57:24 | × | hiyori quits (~hiyori@user/hiyori) (Quit: Client closed) |
| 12:02:46 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 12:04:29 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 12:05:10 | → | vglfr joins (~vglfr@88.155.159.184) |
| 12:09:00 | × | vglfr quits (~vglfr@88.155.159.184) (Remote host closed the connection) |
| 12:09:46 | → | vglfr joins (~vglfr@88.155.159.184) |
| 12:15:21 | → | misterfish joins (~misterfis@87.215.131.102) |
| 12:26:50 | → | danse-nr3 joins (~francesco@151.47.97.45) |
| 12:52:13 | → | alphacentauri joins (alphacenta@gateway/vpn/protonvpn/alphacentauri) |
| 12:56:46 | × | misterfish quits (~misterfis@87.215.131.102) (Ping timeout: 272 seconds) |
| 13:00:58 | × | cfricke quits (~cfricke@user/cfricke) (Quit: WeeChat 4.0.4) |
| 13:01:03 | → | mikoto-chan joins (~mikoto-ch@ip-212-239-236-59.dsl.scarlet.be) |
| 13:02:12 | × | mikoto-chan quits (~mikoto-ch@ip-212-239-236-59.dsl.scarlet.be) (Client Quit) |
| 13:05:13 | × | vglfr quits (~vglfr@88.155.159.184) (Read error: Connection reset by peer) |
| 13:05:34 | → | vglfr joins (~vglfr@149.102.244.98) |
| 13:12:51 | × | wootehfoot quits (~wootehfoo@user/wootehfoot) (Ping timeout: 258 seconds) |
| 13:22:37 | → | ddellacosta joins (~ddellacos@ool-44c738de.dyn.optonline.net) |
| 13:25:16 | → | lisbeths joins (uid135845@id-135845.lymington.irccloud.com) |
| 13:30:21 | → | sabino joins (~sabino@user/sabino) |
| 13:39:40 | → | Simikando joins (~Simikando@adsl-dyn158.91-127-59.t-com.sk) |
| 13:40:11 | → | fendor joins (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) |
| 13:42:29 | × | cpressey quits (~cpressey@host-92-21-195-194.as13285.net) (Quit: Client closed) |
| 13:47:45 | × | shapr quits (~user@2600:1700:c640:3100:e051:bcd9:9086:b34f) (Remote host closed the connection) |
| 13:47:58 | → | shapr joins (~user@2600:1700:c640:3100:fc20:3b33:1ae3:ac4d) |
| 13:52:17 | × | fendor quits (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) (Remote host closed the connection) |
| 13:59:19 | → | notzmv joins (~zmv@user/notzmv) |
| 14:01:02 | → | L29Ah joins (~L29Ah@wikipedia/L29Ah) |
| 14:06:08 | × | Simikando quits (~Simikando@adsl-dyn158.91-127-59.t-com.sk) (Ping timeout: 246 seconds) |
| 14:12:46 | × | vglfr quits (~vglfr@149.102.244.98) (Ping timeout: 272 seconds) |
| 14:14:25 | → | vglfr joins (~vglfr@149.102.244.98) |
| 14:15:24 | × | Square2 quits (~Square4@user/square) (Ping timeout: 240 seconds) |
| 14:15:26 | → | waleee joins (~waleee@2001:9b0:21c:e600:f2f3:f744:435d:137c) |
| 14:18:21 | × | swistak quits (~swistak@185.21.216.141) (Quit: bye bye) |
| 14:18:48 | → | swistak joins (~swistak@185.21.216.141) |
| 14:19:45 | → | Square2 joins (~Square4@user/square) |
| 14:21:48 | × | infinity0 quits (~infinity0@pwned.gg) (Remote host closed the connection) |
| 14:23:39 | → | Square joins (~Square@user/square) |
| 14:23:55 | → | infinity0 joins (~infinity0@pwned.gg) |
| 14:26:27 | → | Simikando joins (~Simikando@adsl-dyn158.91-127-59.t-com.sk) |
| 14:33:02 | × | Square2 quits (~Square4@user/square) (Ping timeout: 272 seconds) |
| 14:33:17 | → | gehmehgeh joins (~user@user/gehmehgeh) |
| 14:34:14 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 14:37:07 | → | thegeekinside joins (~thegeekin@189.180.124.118) |
| 14:39:10 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 255 seconds) |
| 14:42:01 | × | todi quits (~todi@p4fd1a3e6.dip0.t-ipconnect.de) (Ping timeout: 255 seconds) |
| 14:46:20 | → | cpressey joins (~cpressey@host-92-21-195-194.as13285.net) |
| 14:47:48 | × | Simikando quits (~Simikando@adsl-dyn158.91-127-59.t-com.sk) (Ping timeout: 240 seconds) |
| 14:48:16 | → | sm joins (~sm@plaintextaccounting/sm) |
| 15:00:16 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 260 seconds) |
| 15:01:56 | × | danse-nr3 quits (~francesco@151.47.97.45) (Remote host closed the connection) |
| 15:02:16 | → | danse-nr3 joins (~francesco@151.47.97.45) |
| 15:03:20 | × | vglfr quits (~vglfr@149.102.244.98) (Ping timeout: 255 seconds) |
| 15:03:59 | → | [_] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 15:04:11 | → | vglfr joins (~vglfr@88.155.159.184) |
| 15:04:35 | × | [itchyjunk] quits (~itchyjunk@user/itchyjunk/x-7353470) (Read error: Connection reset by peer) |
| 15:11:44 | → | ystael joins (~ystael@user/ystael) |
| 15:16:24 | × | chexum quits (~quassel@gateway/tor-sasl/chexum) (Remote host closed the connection) |
| 15:16:39 | → | chexum joins (~quassel@gateway/tor-sasl/chexum) |
| 15:17:22 | × | waleee quits (~waleee@2001:9b0:21c:e600:f2f3:f744:435d:137c) (Ping timeout: 272 seconds) |
| 15:18:06 | × | alphacentauri quits (alphacenta@gateway/vpn/protonvpn/alphacentauri) (Quit: WeeChat 4.0.5) |
| 15:20:53 | → | alphacentauri joins (alphacenta@gateway/vpn/protonvpn/alphacentauri) |
| 15:23:50 | → | fendor joins (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) |
| 15:24:08 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 15:25:29 | <EvanR> | monochrom, OO extremists insisting on tmp = o1.m1(); o2.m2(tmp); is new to me, but it's funny that is how we have to do stuff in haskell do notation. (idris has syntax which lets you nest them, result <- o2m2 !o1m1; ... |
| 15:27:01 | → | Inst joins (~Inst@120.244.192.250) |
| 15:28:31 | <Inst> | EvanR: why is hybridizing do notation and direct monadic bind considered smelly? |
| 15:28:39 | <dolio> | It isn't. |
| 15:29:00 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) (Remote host closed the connection) |
| 15:29:02 | <Inst> | Because you don't have to do it that way, you can still use function composition in Haskell to achieve the same result as in Idris |
| 15:29:07 | <Inst> | monadic chains, etc |
| 15:29:18 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) |
| 15:29:39 | → | todi joins (~todi@p4fd1a3e6.dip0.t-ipconnect.de) |
| 15:29:53 | <EvanR> | in the above case o1m1 isn't a function (unless you're talking about function monad) |
| 15:30:09 | <c_wraith> | EvanR: well... a = o1.m1(); b = o2.m2(); o3.m3(a, b); Because of side effects, you need to explicitly order them in general. (some languages provide more guarantees than C, but why take chances?) |
| 15:30:46 | × | phma quits (~phma@host-67-44-208-195.hnremote.net) (Read error: Connection reset by peer) |
| 15:30:49 | <EvanR> | yeah I'm down with that style |
| 15:30:55 | × | Square quits (~Square@user/square) (Ping timeout: 255 seconds) |
| 15:30:58 | <EvanR> | but don't blame it on OOP xD |
| 15:31:06 | <c_wraith> | I blamed it on side effects! |
| 15:31:33 | × | Inst quits (~Inst@120.244.192.250) (Client Quit) |
| 15:31:58 | → | phma joins (~phma@host-67-44-208-16.hnremote.net) |
| 15:32:26 | <haskellbridge> | <Inst> yeah, but the order of effects is made explicit by >>=, no? |
| 15:32:37 | <haskellbridge> | <Inst> the only problem in Haskell is that applicatives don't guarantee an order of effect |
| 15:32:41 | <haskellbridge> | <Inst> which makes them potentially smelly |
| 15:32:53 | <c_wraith> | That's actually the whole point of Applicative. |
| 15:33:11 | <c_wraith> | The interface doesn't require ordering. |
| 15:33:37 | <haskellbridge> | <Inst> I was just hoping you could do `liftA2 o3.m3 o1.m1 o2.m2` |
| 15:34:03 | <haskellbridge> | <Inst> well, nope, fff, o3.m3(a,b) implies generated effects |
| 15:34:19 | → | econo_ joins (uid147250@id-147250.tinside.irccloud.com) |
| 15:34:38 | <haskellbridge> | <Inst> you could liftA2 (,) o1.m1 o2.m2 >>= o3.m3, which makes the effect sequence explicit, but w/e, sorry for getting involved |
| 15:37:49 | × | lortabac quits (~lortabac@2a01:e0a:541:b8f0:990f:a737:63e:2e4a) (Ping timeout: 252 seconds) |
| 15:38:52 | × | cpressey quits (~cpressey@host-92-21-195-194.as13285.net) (Quit: Client closed) |
| 15:43:39 | → | Inst joins (~Inst@120.244.192.250) |
| 15:45:48 | × | notzmv quits (~zmv@user/notzmv) (Ping timeout: 240 seconds) |
| 15:46:58 | <probie> | I'm not the biggest fan of `foo !bar !baz`, because it has different semantics to `let foo' = flip foo in foo' !baz !bar` |
| 15:50:29 | <haskellbridge> | <mauke> That looks like a syntax error |
| 15:50:50 | <probie> | That's back in the context of "idris has syntax which lets you nest them" |
| 15:51:36 | <probie> | `foo !bar !baz` being `bar >>= \x -> baz >>= y -> foo x y` |
| 15:52:32 | <probie> | I'm just half an hour late to the discussion |
| 15:52:42 | <haskellbridge> | <mauke> Ah, thanks |
| 15:53:45 | <haskellbridge> | <mauke> Idiom bangs? |
| 15:54:10 | → | _ht joins (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) |
| 15:54:42 | <probie> | http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#notation |
| 15:58:22 | → | Simikando joins (~Simikando@adsl-dyn158.91-127-59.t-com.sk) |
| 16:01:23 | → | sabino1 joins (~sabino@user/sabino) |
| 16:02:23 | → | danse-nr3_ joins (~francesco@151.43.103.136) |
| 16:02:25 | × | sabino quits (~sabino@user/sabino) (Ping timeout: 255 seconds) |
| 16:04:34 | × | Simikando quits (~Simikando@adsl-dyn158.91-127-59.t-com.sk) (Remote host closed the connection) |
| 16:04:39 | × | danse-nr3 quits (~francesco@151.47.97.45) (Ping timeout: 245 seconds) |
| 16:04:57 | → | Simikando joins (~Simikando@adsl-dyn158.91-127-59.t-com.sk) |
| 16:06:32 | sabino1 | is now known as sabino |
| 16:12:24 | → | cpressey joins (~cpressey@host-92-10-148-105.as13285.net) |
| 16:15:08 | → | notzmv joins (~zmv@user/notzmv) |
| 16:15:31 | × | machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 260 seconds) |
| 16:17:12 | × | alphacentauri quits (alphacenta@gateway/vpn/protonvpn/alphacentauri) (Quit: WeeChat 4.0.5) |
| 16:17:23 | × | kuribas quits (~user@ip-188-118-57-242.reverse.destiny.be) (Quit: ERC (IRC client for Emacs 27.1)) |
| 16:20:33 | → | azimut joins (~azimut@gateway/tor-sasl/azimut) |
| 16:20:38 | → | tzh joins (~tzh@c-71-193-181-0.hsd1.or.comcast.net) |
| 16:20:55 | → | alphacentauri joins (alphacenta@gateway/vpn/protonvpn/alphacentauri) |
| 16:23:53 | → | rgw joins (~R@2605:a601:a0df:5600:e1fd:3d46:eec0:9d00) |
| 16:27:00 | × | Simikando quits (~Simikando@adsl-dyn158.91-127-59.t-com.sk) (Quit: Leaving) |
| 16:37:29 | → | stackdroid18 joins (14094@de1.hashbang.sh) |
| 16:40:33 | × | danse-nr3_ quits (~francesco@151.43.103.136) (Remote host closed the connection) |
| 16:44:41 | → | glguy joins (g@libera/staff/glguy) |
| 16:44:59 | × | g quits (g@libera/staff/glguy) (Read error: Connection reset by peer) |
| 16:45:26 | × | ghoulguy quits (g@libera/staff/glguy) (Read error: Connection reset by peer) |
| 16:47:09 | → | rncwnd joins (~quassel@2a01:4f8:221:27c6::1) |
| 16:47:13 | glguy | is now known as ghoulguy |
| 16:47:52 | → | g joins (g@libera/staff/glguy) |
| 16:49:12 | × | dsrt^ quits (~cd@76.145.193.217) (Ping timeout: 272 seconds) |
| 16:49:33 | × | cuiltb^ quits (~cd@76.145.193.217) (Remote host closed the connection) |
| 16:49:40 | <monochrom> | I carefully chose my example! Of course f(m1a(), m1b()) would be ambiguos. But f(m1a()) isn't. |
| 16:49:51 | → | cuiltb^ joins (~cd@76.145.193.217) |
| 16:50:03 | <monochrom> | Nor is f(g(h())). |
| 16:50:36 | <c_wraith> | my point was merely that style guides come from paranoia. Can it mess up in case A? then mandate it for case B, too |
| 16:50:52 | <monochrom> | Ah OK I agree. :) |
| 16:51:12 | <monochrom> | Extremism comes from paranoia too >:) |
| 16:51:38 | → | dsrt^ joins (~cd@76.145.193.217) |
| 16:55:11 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:9d50:ee50:b066:e718) (Remote host closed the connection) |
| 16:58:06 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:8de0:2b83:d0e7:f73b) |
| 16:59:55 | <haskellbridge> | <Inst> what do you mean by the point of applicative is that there's no specified order of effects? |
| 17:00:03 | <haskellbridge> | <Inst> for instance, in monochrom's examples |
| 17:00:03 | × | stackdroid18 quits (14094@de1.hashbang.sh) (Quit: hasta la vista... tchau!) |
| 17:00:15 | → | zenstoic joins (uid461840@id-461840.hampstead.irccloud.com) |
| 17:00:40 | <haskellbridge> | <Inst> that might be manual bind onto liftA2 |
| 17:02:26 | <haskellbridge> | <Inst> for instance, i know how with the async applicative, the concurrency comes from not having to specify an order of effects |
| 17:05:49 | <probie> | Applicative consists of `pure` and `<*>` |
| 17:05:54 | <probie> | :t (<*>) |
| 17:05:55 | <lambdabot> | Applicative f => f (a -> b) -> f a -> f b |
| 17:06:11 | <probie> | :t (>>=) |
| 17:06:11 | <lambdabot> | Monad m => m a -> (a -> m b) -> m b |
| 17:06:21 | <dolio> | There is a specified order, though. |
| 17:06:39 | <haskellbridge> | <Inst> i mean i know bind is a monad method |
| 17:08:17 | × | stefan-_ quits (~cri@42dots.de) (Quit: ZNC 1.8.2+deb2build5 - https://znc.in) |
| 17:08:18 | × | stefan-__ quits (~m-ohzqow@42dots.de) (Read error: Connection reset by peer) |
| 17:08:58 | → | stefan-_ joins (~cri@42dots.de) |
| 17:09:21 | × | John_Ivan__ quits (~John_Ivan@user/john-ivan/x-1515935) (Quit: Disrupting the dragon's slumber one time too often shall eventually bestow upon all an empirical and indiscriminate conflagration that will last for all goddamn eternity.) |
| 17:11:27 | <haskellbridge> | <Inst> whoops, not async, i mean Concurrently |
| 17:16:16 | <probie> | It's 4am my time, so my brain has not yet turned on. But perhaps it might be useful to write a `Functor` and `Applicative` instance for `newtype Errors err a = Errors (Either (NonEmpty err) a)` with the expected semantics `Errors (Left e1) <*> Errors (Left e2) = Errors (Left (e1 <> e2))` and why you can't write a `Monad` instance for it |
| 17:16:43 | <probie> | It's not really "no specified order of effects" as much as "no dependency" |
| 17:18:40 | <tomsmeding> | you can write a Monad instance for it, it will just not give errors for the continuation of a bind if its left-hand side errored :p |
| 17:19:19 | <haskellbridge> | <Inst> iirc, i noted that you can get a monad instance for Concurrently |
| 17:19:30 | × | chele quits (~chele@user/chele) (Remote host closed the connection) |
| 17:19:47 | <probie> | tomsmeding: Hence the "with the expected semantics..." constraint |
| 17:20:05 | <tomsmeding> | right |
| 17:20:08 | <haskellbridge> | <Inst> since it's just a newtype around IO |
| 17:20:12 | <haskellbridge> | <Inst> and it'd be lawful too |
| 17:21:03 | <tomsmeding> | you'd have to be careful to write things that you'd like to be concurrent using the applicative combinators, though |
| 17:22:03 | <haskellbridge> | <Inst> i'm just wondering for what principle the monad instance is avoided, though |
| 17:22:24 | <haskellbridge> | <Inst> in a mathematical sense, is Concurrently a Monad? |
| 17:22:31 | <probie> | I don't think it'd be lawful, since you probably wouldn't be able to satisfy `m1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))` |
| 17:23:01 | <haskellbridge> | <Inst> monad laws i'm not familiar with? !! |
| 17:23:21 | <tomsmeding> | I don't know anything about this particular functor we're talking about, but is the point just that independent effects are evaluated in parallel? |
| 17:23:23 | <haskellbridge> | <Inst> i guess it'd break ap, but i'm not familiar with laws associated with that |
| 17:23:48 | <tomsmeding> | oh right, the effects would not be evaluated in the same order |
| 17:23:50 | <haskellbridge> | <Inst> https://hackage.haskell.org/package/async-2.2.4/docs/Control-Concurrent-Async.html#t:Concurrently |
| 17:24:24 | <tomsmeding> | yeah a <*> b and (liftM2 ($) a b) would have the same _value_ result, but might execute effects in a different order |
| 17:24:30 | <tomsmeding> | after all, that's the whole point of Concurrently! |
| 17:24:45 | <tomsmeding> | so it's not _quite_ a lawful Monad |
| 17:24:51 | <dolio> | Sure it is. |
| 17:25:27 | <tomsmeding> | dolio: that equality in the law seems pretty strong |
| 17:25:47 | <haskellbridge> | <Inst> it's an interesting edge case imo, i.e, you can have a lawful monad implementation, but the point is that the applicative implementation is both lawful and different. and the library authors elected to omit the monad implementation, probably for obvious reasons |
| 17:26:03 | <haskellbridge> | <Inst> `m1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))` |
| 17:26:10 | <haskellbridge> | <Inst> which law is this? |
| 17:26:12 | <dolio> | You just define equality so that different concurrent executions resulting in the same value are considered equal. |
| 17:26:23 | <dolio> | Since that's the whole point of the thing. |
| 17:26:26 | × | stefan-_ quits (~cri@42dots.de) (Quit: ZNC 1.8.2+deb2build5 - https://znc.in) |
| 17:26:38 | <tomsmeding> | Inst: see the "Furthermore, ..." in the haddocks for Monad |
| 17:27:00 | → | stefan-_ joins (~cri@42dots.de) |
| 17:27:08 | <tomsmeding> | dolio: does the implementer of an _instance_ of Monad get to decide what the symbols in the laws of Monad mean? |
| 17:27:15 | <tomsmeding> | I'm not sure that's what the point of laws is :D |
| 17:27:16 | <dolio> | Yes, of course. |
| 17:28:15 | → | wootehfoot joins (~wootehfoo@user/wootehfoot) |
| 17:28:29 | <tomsmeding> | so I can write a Monad instance for my favourite data type, have it flaunt all reason, and declare it lawful because it satisfies the laws if you interpret equality as "tomsmeding thinks they look similar"? |
| 17:28:37 | <tomsmeding> | surely that's not what "lawful" means |
| 17:29:17 | <dolio> | You can do that if you want. No one will use it, because your criterion for equality is not useful. |
| 17:29:23 | <tomsmeding> | I mean, I agree that this discrepancy is the entire point of Concurrently, and I would not be against a Monad instance there |
| 17:29:44 | <tomsmeding> | dolio: do you also consider Validation to be a lawful Monad? |
| 17:29:59 | <tomsmeding> | (where (<*>) preserves more errors than `ap`) |
| 17:30:16 | <Inst> | that's an interesting limitation, never thought of that before |
| 17:30:45 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:8de0:2b83:d0e7:f73b) (Remote host closed the connection) |
| 17:31:01 | <tomsmeding> | also with this reasoning, classical ListT, which is considered "only a monad when wrapping a commutative monad", is actually always a monad if you consider equality modulo reordering of effects |
| 17:31:06 | <dolio> | It depends on the context. If getting all the errors matter, then no. If just getting some collection of errors is all that matters, then it's fine. |
| 17:31:35 | <Inst> | wait, so if you're working with values of type concurrently, can you place it into do notation? |
| 17:31:39 | <tomsmeding> | hm, I can live with context-dependent equality and hence context-dependent lawfulness |
| 17:31:44 | <Inst> | how about with -XApplicativeDo? |
| 17:31:52 | <tomsmeding> | Inst: with ApplicativeDo, yes |
| 17:31:59 | <tomsmeding> | as long as you don't introduce a data dependency |
| 17:32:07 | <Inst> | i mean, not for binding, but just for stringing... |
| 17:32:09 | <tomsmeding> | (which would require (>>=)) |
| 17:32:13 | <Inst> | and iirc, isn't applicativeDo a misfeature? |
| 17:32:17 | <tomsmeding> | :t do 42 |
| 17:32:18 | <lambdabot> | Num p => p |
| 17:32:25 | <tomsmeding> | what is a "misfeature" |
| 17:32:45 | <Inst> | i've heard it criticized for having a terrible desugaring algorithm that can result in very long compile times |
| 17:32:51 | <tomsmeding> | sure |
| 17:32:52 | <dolio> | All monads are not lawful if you look hard enough for reasons to disqualify them. You have to actually think about what matters. |
| 17:32:56 | <tomsmeding> | does that mean it's a "misfeature"? |
| 17:33:30 | <tomsmeding> | dolio: thanks, I hadn't considered this perspective on typeclass laws before |
| 17:33:34 | → | idgaen joins (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) |
| 17:33:41 | <Inst> | hmmm |
| 17:33:49 | <tomsmeding> | it does make communication harder, because people typically do not state what they use as "equality" when interpreting the laws for their instance |
| 17:35:08 | <Inst> | semanntically, then |
| 17:35:11 | <geekosaur> | ApplicativeDo isn't just potentially long compile times, it's also pickier than it needs to be and therefore small changes to code can break it (cause it to infer a Monad constraint instead) |
| 17:35:19 | <geekosaur> | But the concept is not bad |
| 17:35:20 | <tomsmeding> | though the informal default of "same result and same effects" is probably used by almost everyone unless stated otherwise |
| 17:35:32 | <Inst> | Concurrently is a Monad in the way we usually use the term, right? |
| 17:35:40 | <tomsmeding> | what is the way we usually use the term |
| 17:35:45 | <tomsmeding> | that's the whole point of this conversation :p |
| 17:36:02 | <probie> | "same effects" is rather hand-wavy, since we'd probably call sparking a new thread an effect, but maybe not an additional memory allocation? |
| 17:36:13 | <tomsmeding> | I was implicitly assuming a definition in which Concurrently is technically not a monad |
| 17:36:14 | <Inst> | a Monad, as we say it, means a type which can have a lawful instancing into the class Monad |
| 17:36:19 | <tomsmeding> | dolio was arguing that it should be context-dependent |
| 17:36:28 | <tomsmeding> | probie: true |
| 17:36:39 | <tomsmeding> | Inst: "lawful" is ambiguous |
| 17:36:48 | <geekosaur> | Inst, but the definition of "lawful" was in question a few minutes ago |
| 17:36:53 | <tomsmeding> | because there's various ways you can interpret the equalities |
| 17:37:02 | <tomsmeding> | that was the whole bloody conversation :p |
| 17:37:54 | → | stefan-__ joins (~m-ohzqow@42dots.de) |
| 17:38:12 | <Inst> | i guess i'm having a different semantic argument |
| 17:38:38 | × | cpressey quits (~cpressey@host-92-10-148-105.as13285.net) (Quit: Client closed) |
| 17:38:51 | <Inst> | if you treat Concurrently as a newtype over IO, there exists a pair of an applicative and monad instances which satisfy the monad laws |
| 17:38:57 | <EvanR> | some definitions of equality are more equal than others |
| 17:39:12 | <Inst> | which is not concurrently's actual applicative instance |
| 17:39:32 | <tomsmeding> | Inst: you're now interpreting the equalities as requiring execution of effects in the same order |
| 17:39:37 | <probie> | `ZipList`s have the same problem |
| 17:40:06 | <tomsmeding> | the effects of the contained IO operations, that is |
| 17:40:08 | <Inst> | ugh, my definition of how we use the word Monad to describe types is now messed up :( |
| 17:40:26 | <dolio> | "To define a set we prescribe, at least implicitly, what we (the constructing intelligence) must do in order to construct an element of the set, and what we must do to show that two elements of the set are equal." -- Bishop |
| 17:40:31 | <Inst> | and i'd see it as requiring execution of effects in the same order |
| 17:40:45 | <Inst> | remember, in Haskell, there's an explicit notion of effect that can be contained by monadic types |
| 17:41:02 | <Inst> | so the effect is baked into the value |
| 17:41:24 | <tomsmeding> | Inst: I agree on one hand |
| 17:41:36 | <probie> | `Functor` is friendly because a type only admits one meaningful instance, `Applicative` on the other hand, doesn't have that limitation |
| 17:41:50 | <tomsmeding> | on the other hand, if you're using Concurrently, you're kind of explicitly waiving the guarantee that your effects are executed in a deterministic order |
| 17:42:17 | <tomsmeding> | a <*> b is not even equal to a <*> b because the effect order is nondeterministic |
| 17:42:30 | <Inst> | ugh, i'd probably need to spend a lot of time thinking about this |
| 17:42:34 | <tomsmeding> | let alone any non-tautological law :p |
| 17:42:53 | <monochrom> | Ugh, that should not be how you define "equal". |
| 17:42:57 | → | ursa-major joins (~ursa-majo@static-198-44-128-153.cust.tzulo.com) |
| 17:43:13 | <tomsmeding> | so if Concurrently is to be a lawful Applicative, with that same notion of equality (modulo effect reordering), it's also a Monad with the obvious implementation of (>>=) :p |
| 17:43:57 | <monochrom> | C programmers can be excused to say "rand() does not equal rand()" because by Sapir-Whorf they only know to compare return values of rand(). |
| 17:44:09 | <monochrom> | (and because the "type" is "int".) |
| 17:44:43 | <tomsmeding> | oooh |
| 17:44:57 | <monochrom> | We have learned from Haskell that the true type is "IO Int" so rand == rand alright. Equality for IO Int means equivalent behaviour. |
| 17:45:00 | <tomsmeding> | monochrom: you're saying that it's a lawful applicative because both LHS and RHS of the laws have nondeterministic effect orders |
| 17:45:08 | <tomsmeding> | so they are indeed observationally equal |
| 17:45:23 | <monochrom> | To be sure it takes a lot of effort to write down the denotational semantics of IO but equality should be based on that. |
| 17:45:29 | <Inst> | afaik the nondeterministic effect is conceptualized and baked into the definition? |
| 17:46:12 | <tomsmeding> | Inst: which definition do you mean? |
| 17:46:23 | <Inst> | the definition of the value? |
| 17:46:26 | <tomsmeding> | which value |
| 17:46:32 | <Inst> | so then a <*> b <===> a <*> b |
| 17:46:39 | <tomsmeding> | right |
| 17:46:42 | <monochrom> | Nondeterminism does not change this consideration. You are comparing one set of all possible execution traces with another such set. |
| 17:46:54 | <tomsmeding> | right |
| 17:46:57 | <probie> | With `Concurrently`, you don't get equivalent behaviour as regular `IO`, because if in `f <*> g`, both `f` and `g` can raise exceptions, `IO` will always raise the exception for `f`, but `Concurrently` will non-deterministically return one of the exceptions for `f` or `g` |
| 17:47:11 | → | danza joins (~francesco@151.43.103.136) |
| 17:47:19 | <tomsmeding> | but if re-associate (<*>), you have the same non-determinism |
| 17:47:22 | <tomsmeding> | hence the Applicative laws hold |
| 17:47:39 | <tomsmeding> | yep, scratch the... some of my remarks above |
| 17:47:56 | <tomsmeding> | but under that reasoning surely 'm1 <*> m2 = m1 >>= (\x1 -> m2 >>= (\x2 -> return (x1 x2)))' doesn't hold |
| 17:48:06 | <monochrom> | (forkIO foo >> forkIO bar >> pure ()) = (forkIO bar >> forkIO foo >> pure()) because they are the same set of possible behaviours. |
| 17:48:15 | <tomsmeding> | because the LHS has executions that are impossible on the RHS |
| 17:48:49 | <Inst> | so, then, what is Concurrently? |
| 17:48:55 | <tomsmeding> | a lawful Applicative |
| 17:49:00 | <Inst> | is it defined by its specific applicative instance? |
| 17:49:01 | <tomsmeding> | and an almost-lawful Monad |
| 17:49:05 | <tomsmeding> | of course |
| 17:49:08 | <Inst> | or by any possible applicative instance? |
| 17:49:28 | <tomsmeding> | Data.Monoid.Sum and Data.Monoid.Product are different types because they have different Monoid instances |
| 17:49:38 | <tomsmeding> | even though the data types themselves are isomorphic |
| 17:49:48 | <tomsmeding> | ZipList and [] are not the same |
| 17:49:54 | <Inst> | okay, then, Concurrently cannot be a monad for breaking additional monad laws relating applicative to monad |
| 17:50:04 | <tomsmeding> | unless, that is, you don't care about the instances -- "sameness" may be context-dependent |
| 17:50:06 | <Inst> | this was insightful and interesting, thanks for the education |
| 17:50:12 | <tomsmeding> | yep |
| 17:50:41 | <tomsmeding> | though, still, I would have little objection to a Monad instance |
| 17:51:01 | <Inst> | just from a pragmatic point of view, i'd still object to it because it'd create unwanted expectations |
| 17:51:19 | <tomsmeding> | I mean, you'd need to document it |
| 17:51:24 | <probie> | I would strongly object, because it would almost always be an accident to use for `Concurrently` |
| 17:51:30 | <tomsmeding> | would it? |
| 17:51:45 | <Inst> | ummm, it'd be a footgun, no? |
| 17:51:59 | <tomsmeding> | hm, I guess because Concurrently is not a monad transformer, you can just runConcurrently every time you have a data dependency |
| 17:52:01 | <probie> | If you're using `Concurrently`, you probably not very far away from `IO` |
| 17:52:16 | <probie> | s/you probably/you are probably/ |
| 17:52:23 | <Inst> | and if you're chaining it via XApplicativeDo, there is no way to tell when slight mistakes in coding cause ApplicativeDo to resort to monad desugaring |
| 17:52:30 | <dolio> | Given how ApplicativeDo works, you could easily be accidentally pessimising yourself if you didn't get errors when it flips over to Monad. |
| 17:52:38 | <Inst> | except when the benchmarks fail |
| 17:52:42 | <tomsmeding> | true |
| 17:52:53 | <tomsmeding> | good points |
| 17:53:08 | <tomsmeding> | I would perhaps just not use ApplicativeDo at all |
| 17:53:11 | <tomsmeding> | but it's a footgun for sure |
| 17:53:26 | <monochrom> | This is why for a Monad instance, we require that equation between <*> and >>= . |
| 17:53:52 | <monochrom> | OTOH once in a while there is an exceptional just cause to deviate... |
| 17:54:50 | <monochrom> | Then people start arguing elastic social convention vs inelastic sacred commandments. |
| 17:55:14 | <Inst> | and there is a very useful term for it, "unlawful monad" |
| 17:55:36 | <monochrom> | I got attracted to programming because I wanted to stay away from people issues. Turns out there is no escape. >:) |
| 17:56:04 | <monochrom> | Hell, to a 10% extent, even s/people issues/people/ |
| 17:56:21 | <tomsmeding> | you failed, you're too active in #haskell |
| 17:56:34 | <monochrom> | Right? When a human says "yes", it doesn't even always mean "yes". |
| 17:56:59 | <monochrom> | But if the computer says "OK" then it really simply means "OK". |
| 17:57:03 | <monochrom> | Similarly, math. |
| 17:57:15 | <Inst> | "words are like nets, meaning is like fish" |
| 17:57:20 | <tomsmeding> | but what that "OK" in turn means might be surprising :p |
| 17:57:22 | <Inst> | you can spend all day trying to decipher what people really mean |
| 17:58:25 | <Inst> | also, with the runConcurrently stuff |
| 17:58:43 | <tomsmeding> | cabal, for a few versions, interpreted the exit status of a post-checkout-command in a cabal.project the wrong way round |
| 17:58:49 | <tomsmeding> | exit code 1 was success, exit code 0 was failure |
| 17:58:54 | <tomsmeding> | they fixed it recently |
| 17:59:01 | <tomsmeding> | OK doesn't always mean OK monochrom |
| 17:59:34 | <tomsmeding> | I now have some cabal.projects around that have a ! before their command, and I have to fix them up when working in that folder again |
| 17:59:34 | <monochrom> | OK computers have bugs. Or someone wrote the wrong message to print in the code. |
| 17:59:47 | <Inst> | put another way, the deep meaning of code is more visible than with people, because you have all the information needed to understand the actual computation |
| 17:59:56 | <dolio> | Haskell just doesn't give you enough machinery to specify what equality is, per Bishop. |
| 17:59:57 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:e9d7:8bce:4928:5b34) |
| 18:00:01 | <Inst> | meanwhile, modeling everything someone knows, everything they're thinking, etc, all that information is hidden |
| 18:00:18 | <monochrom> | I just mean a fairly bugless compiler/interpreter, when it says "syntax error" then I truly have a syntax error, if it says "no syntax error" then it truly means no syntax error. |
| 18:00:37 | → | jumper joins (~jumper@mobile-access-6df060-87.dhcp.inet.fi) |
| 18:01:01 | <Inst> | wb jumper, hope your questions get resolved adequately today :) |
| 18:01:27 | <tomsmeding> | monochrom: perhaps we can say: at least programs tend to strive towards this property |
| 18:01:34 | <tomsmeding> | people, not necessarily |
| 18:02:27 | → | qqq joins (~qqq@92.43.167.61) |
| 18:03:11 | <monochrom> | OK sometimes it's the flip side. What I say vs what the computer or human thinks I mean. |
| 18:03:24 | <monochrom> | Suppose I say "print x" but I didn't say "print y". |
| 18:03:35 | × | sm quits (~sm@plaintextaccounting/sm) (Ping timeout: 240 seconds) |
| 18:03:40 | <jumper> | Inst, function definitions in Haskell and function calls, are they similar as in math? f :: Int -> Int ; f i = i + 1 ; f 1 |
| 18:03:47 | <monochrom> | A computer reliably predictably unwailining honours exactly that, no more no less. |
| 18:03:58 | <Inst> | i don't know, ask someone else :( |
| 18:04:06 | <monochrom> | Humans? They start second-guessing me and guess wrong. |
| 18:04:12 | × | danza quits (~francesco@151.43.103.136) (Read error: Connection reset by peer) |
| 18:05:11 | <monochrom> | Programming languages are a relief to me because I just have to say what I mean and not worry that it needs further "clarifications". |
| 18:05:31 | <monochrom> | With humans, it's telephone games all the way down. |
| 18:05:34 | tomsmeding | . o O ( INTERCAL ) |
| 18:06:16 | <monochrom> | But OK, eventually, one learns that a computer consists of a million layers of abstractions, so it is still telephone games all the way down. >:) |
| 18:06:16 | <EvanR> | jumper, don't get too caught up in concrete syntax too much |
| 18:06:48 | <EvanR> | sin pi, sin(pi), it's really not an interesting decision to dwell on |
| 18:06:52 | → | sm joins (~sm@plaintextaccounting/sm) |
| 18:07:11 | <EvanR> | it's parsed into the same thing |
| 18:07:33 | <EvanR> | (application of sin to pi) |
| 18:07:51 | <monochrom> | Actually, I put it wrong. I just have to know that the computer reliably takes what I say at face value and not try to "read between the lines" and start putting words into my mouth. |
| 18:09:42 | <Inst> | monochrom: there's possibly a cultural dimension to your criticism, but I think that's off-topic |
| 18:10:05 | <monochrom> | Yeah I was about to stop. But just one last erratum. |
| 18:11:50 | <monochrom> | It is impossible to answer "are they similar?" in most cases. |
| 18:11:51 | <jumper> | Is it possible in haskell to express \xy.x, that is, \x.\y.x, in Haskell aswell without the extra arrow? f :: x -> y -> x ; |
| 18:12:02 | <monochrom> | https://www.vex.net/~trebla/humour/tautologies.html #0 |
| 18:12:12 | <tomsmeding> | :t \x y -> x |
| 18:12:13 | <lambdabot> | p1 -> p2 -> p1 |
| 18:12:29 | <EvanR> | perhaps you want (x,y) -> x i.e. pass in a pair |
| 18:12:35 | <EvanR> | uncurrying |
| 18:12:41 | <monochrom> | Or perhaps equivalently, it is always trivial to answer, the correct answer is always "they are similar, but different :)" |
| 18:13:09 | <EvanR> | but if you want to express \x -> \y -> x, that is literally two arrows |
| 18:13:23 | <tomsmeding> | monochrom: that could be a tautology for the list, "These two things are similar but different" |
| 18:13:28 | → | glguy joins (g@libera/staff/glguy) |
| 18:13:34 | × | g quits (g@libera/staff/glguy) (Read error: Connection reset by peer) |
| 18:13:36 | → | g_ joins (g@libera/staff/glguy) |
| 18:13:37 | g_ | is now known as g |
| 18:13:39 | <monochrom> | Haskell "\x y -> foo" is syntax sugar for "\x -> (\y -> foo)" |
| 18:13:40 | × | ghoulguy quits (g@libera/staff/glguy) (Read error: Connection reset by peer) |
| 18:13:46 | glguy | is now known as ghoulguy |
| 18:14:07 | <geekosaur> | is lambda calculus \xy.x even well formed? |
| 18:14:18 | <EvanR> | you can define that shorthand |
| 18:14:25 | <monochrom> | tomsmeding, I thought #0 already covers that :) |
| 18:14:48 | <tomsmeding> | yeah I guess true :p |
| 18:14:50 | <Inst> | i like the contradiction, i.e, the tautology list is basically why people try to read between the lines |
| 18:15:19 | <monochrom> | I think everyone defines "lambda x y . foo" or "lambda x, y . foo" to mean nested lambdas. |
| 18:16:19 | → | hiyori joins (~hiyori@user/hiyori) |
| 18:16:27 | <monochrom> | Including Church. He used the comma version. |
| 18:16:48 | <monochrom> | Actually maybe I don't actually remember whether he used comma or not. |
| 18:16:59 | <monochrom> | My thesis supervisor uses comma. :) |
| 18:18:39 | <EvanR> | \x y z . whatever is sugar for nested lambdas, because in LC every function takes one arugment. And then GHC baits and switches by compiling things to multi-arg functions after all! |
| 18:19:33 | <monochrom> | Well, you can't blame GHC for compiling to the von Neumann model which has no idea what lambda even means. |
| 18:19:33 | <EvanR> | what you see is what you get |
| 18:20:05 | <monochrom> | Alternatively, you can't blame GHC for trying to compile to faster code. |
| 18:20:51 | <dolio> | Church does not use commas, at least in the reprint book I have. |
| 18:21:15 | <monochrom> | Compiling to "function f(x) { return yet another function }" is going to give you dog slow code. Then everyone will complain "Haskell is not ready for prime time because it's too slow." Remember those days? |
| 18:22:15 | <monochrom> | Ah thanks dolio. |
| 18:22:29 | <EvanR> | now that it's fast, we need another reason it's not ready for prime time. Because avoid success |
| 18:22:45 | <EvanR> | avoiding success doesn't happen on its own |
| 18:22:56 | <monochrom> | Oh, the next "reason" was "toolchain" >:) |
| 18:23:13 | <EvanR> | there we go |
| 18:23:17 | <monochrom> | And then the next next reason was "two toolchains" >:D |
| 18:24:09 | → | acidjnk_new joins (~acidjnk@p200300d6e72b933890137bb0a9c5386a.dip0.t-ipconnect.de) |
| 18:24:47 | × | acidjnk quits (~acidjnk@p200300d6e7072f57652bd3d039ad030c.dip0.t-ipconnect.de) (Ping timeout: 246 seconds) |
| 18:26:02 | <monochrom> | Some time between them there was also "Windows". |
| 18:28:14 | <jumper> | have there been any trials to write an operating system using Haskell alone with some basic low level library support? |
| 18:29:02 | <geekosaur> | House |
| 18:29:09 | → | misterfish joins (~misterfis@84-53-85-146.bbserv.nl) |
| 18:30:33 | <geekosaur> | https://github.com/dls/house |
| 18:30:48 | <geekosaur> | also has haskellwiki and wikipedia entries |
| 18:30:55 | <jumper> | cool |
| 18:33:35 | <ncf> | > House (acronym for Haskell User's Operating System and Environment) |
| 18:33:37 | <lambdabot> | error: |
| 18:33:37 | <lambdabot> | Data constructor not in scope: House :: t0 -> terror: |
| 18:33:37 | <lambdabot> | Variable not in scope: |
| 18:33:39 | ncf | squints |
| 18:34:46 | → | Tuplanolla joins (~Tuplanoll@91-159-68-236.elisa-laajakaista.fi) |
| 18:34:56 | × | urdh quits (~urdh@user/urdh) (Quit: Boom!) |
| 18:35:01 | × | sm quits (~sm@plaintextaccounting/sm) (Quit: sm) |
| 18:35:17 | × | hiyori quits (~hiyori@user/hiyori) (Quit: Client closed) |
| 18:35:35 | → | hiyori joins (~hiyori@user/hiyori) |
| 18:35:38 | <geekosaur> | evidently is doesn't include a spell checker 😛 |
| 18:35:45 | <geekosaur> | *ti |
| 18:35:46 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 18:35:48 | <geekosaur> | *it |
| 18:35:51 | → | urdh joins (~urdh@user/urdh) |
| 18:36:01 | geekosaur | looks at fingers suspiciously |
| 18:37:10 | × | urdh quits (~urdh@user/urdh) (Client Quit) |
| 18:37:28 | → | emmanuelux_ joins (~emmanuelu@user/emmanuelux) |
| 18:40:12 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 240 seconds) |
| 18:40:22 | × | emmanuelux quits (~emmanuelu@user/emmanuelux) (Ping timeout: 255 seconds) |
| 18:41:57 | → | urdh joins (~urdh@user/urdh) |
| 18:44:44 | → | danza joins (~francesco@151.47.109.198) |
| 18:49:35 | × | urdh quits (~urdh@user/urdh) (Quit: Boom!) |
| 18:52:09 | → | urdh joins (~urdh@user/urdh) |
| 18:53:37 | <int-e> | "-> terror", nice. |
| 18:54:11 | <int-e> | (no clue what happened to that newline) |
| 18:54:48 | <Unicorn_Princess> | what's the difference between {-# OPTIONS .. #-} and {-# OPTIONS_GHC .. #-}, and when should each be used? specifically for disabling warnings, in case the question is too big |
| 18:55:11 | <Unicorn_Princess> | (both seem to work) |
| 18:55:25 | × | actioninja quits (~actioninj@user/actioninja) (Quit: Ping timeout (120 seconds)) |
| 18:55:26 | × | Katarushisu1 quits (~Katarushi@cpc147790-finc20-2-0-cust502.4-2.cable.virginm.net) (Quit: Ping timeout (120 seconds)) |
| 18:55:29 | <int-e> | I suspect that OPTIONS would apply to other Haskell compilers or interpreters too. |
| 18:55:50 | → | actioninja joins (~actioninj@user/actioninja) |
| 18:55:53 | <geekosaur> | not that there are any these days, but I'd still stick to OPTIONS_GHC |
| 18:55:55 | <int-e> | (Which used to be more numerous than they are today.) |
| 18:56:08 | → | hamess joins (~hamess@user/hamess) |
| 18:56:18 | <ddellacosta> | Unicorn_Princess: looks like they are the same, but OPTIONS is deprecated https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/pragmas.html?highlight=pragmas#options-ghc-pragma |
| 18:56:40 | <Unicorn_Princess> | ah, thanks |
| 18:57:25 | <Clint> | it's been marked as deprecated for ages |
| 18:58:01 | → | Katarushisu1 joins (~Katarushi@cpc147790-finc20-2-0-cust502.4-2.cable.virginm.net) |
| 19:02:38 | <monochrom> | Procrastination is universal. >:) |
| 19:02:59 | → | ft joins (~ft@p3e9bc680.dip0.t-ipconnect.de) |
| 19:07:44 | × | ursa-major quits (~ursa-majo@static-198-44-128-153.cust.tzulo.com) (Quit: WeeChat 4.0.5) |
| 19:08:21 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:e9d7:8bce:4928:5b34) (Remote host closed the connection) |
| 19:08:56 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:e9d7:8bce:4928:5b34) |
| 19:09:29 | <Franciman> | procrastination is final, all objects map to it |
| 19:10:26 | → | waleee joins (~waleee@2001:9b0:21c:e600:f2f3:f744:435d:137c) |
| 19:11:17 | × | danza quits (~francesco@151.47.109.198) (Ping timeout: 255 seconds) |
| 19:13:21 | × | eggplantade quits (~Eggplanta@2600:1700:38c5:d800:e9d7:8bce:4928:5b34) (Ping timeout: 260 seconds) |
| 19:16:03 | <tomsmeding> | I expect support for OPTIONS will never be removed, there is too much code using it :p |
| 19:16:28 | <tomsmeding> | and, until a new competing compiler arrives, there is little benefit in removing it |
| 19:21:34 | → | sm joins (~sm@plaintextaccounting/sm) |
| 19:21:52 | × | Unicorn_Princess quits (~Unicorn_P@user/Unicorn-Princess/x-3540542) (Remote host closed the connection) |
| 19:22:02 | <EvanR> | I approve of the portmanteau terror for type error |
| 19:22:13 | <EvanR> | very seasonal |
| 19:22:39 | <juri_> | so, what's the process for taking over a package that appears abandoned by it's maintainer? tl;dr: floating-bits is breaking me, because it is not compatible with newer GHCs. |
| 19:24:02 | <geekosaur> | https://wiki.haskell.org/Taking_over_a_package |
| 19:24:24 | <tomsmeding> | you even had the right search term already ;) |
| 19:24:53 | <Clint> | there's also https://github.com/haskell-infra/hackage-trustees/issues |
| 19:30:58 | → | cpressey joins (~cpressey@host-92-10-148-105.as13285.net) |
| 19:46:34 | × | benjaminl quits (~benjaminl@user/benjaminl) (Remote host closed the connection) |
| 19:46:53 | → | benjaminl joins (~benjaminl@user/benjaminl) |
| 19:47:03 | × | Yumemi quits (~Yumemi@2001:bc8:47a0:1b14::1) (Quit: .) |
| 19:47:29 | <EvanR> | there are various ways to implement a custom "app monad" with a bunch of features. Which one gives the most performance |
| 19:47:43 | <EvanR> | freer? |
| 19:47:55 | → | Yumemi joins (~Yumemi@chamoin.net) |
| 19:48:45 | <EvanR> | is that the one the church encodes the functor of actions |
| 19:49:58 | <tomsmeding> | are you looking for algebraic effects? |
| 19:50:26 | <tomsmeding> | if you're not doing algebraic effects, don't go with free monads |
| 19:51:11 | <EvanR> | is it slower |
| 19:51:15 | <tomsmeding> | yes |
| 19:51:19 | <tomsmeding> | ReaderT env IO |
| 19:51:24 | <tomsmeding> | is your friend if you want performance |
| 19:51:39 | <EvanR> | and use IO exceptions to do stuff like cancel a computation early? |
| 19:51:54 | <tomsmeding> | IO exceptions are faster than Either, yes |
| 19:52:10 | <tomsmeding> | if you're already in IO anyway |
| 19:52:23 | <EvanR> | what about env -> IO, is it even faster xD |
| 19:52:36 | <tomsmeding> | @unmtl ReaderT env IO |
| 19:52:36 | <lambdabot> | err: `ReaderT env IO' is not applied to enough arguments, giving `/\A. env -> IO A' |
| 19:52:40 | <tomsmeding> | @unmtl ReaderT env IO a |
| 19:52:40 | <lambdabot> | env -> IO a |
| 19:52:52 | <tomsmeding> | it's a newtype over the same thing, so same |
| 19:53:24 | <monochrom> | The only difference is what your code looks like. |
| 19:53:27 | <EvanR> | this isn't the answer I was expecting but I guess I'm not surprised |
| 19:53:38 | <tomsmeding> | EvanR: the reader monad _is_ r-> |
| 19:53:40 | <EvanR> | simple haskell for the win |
| 19:54:01 | <tomsmeding> | when people talk about the venerable function monad for advanced point-free tricks, that's the reader monad |
| 19:54:04 | <tomsmeding> | just without the newtype wrapper |
| 19:54:43 | <geekosaur> | sanity wrapper 🙂 |
| 19:55:34 | <tomsmeding> | > ((,) <$> (+ 1) <*> (* 2)) 10 |
| 19:55:36 | <lambdabot> | (11,20) |
| 19:56:09 | <tomsmeding> | coerce (+ 1) :: Num a => Reader a a |
| 19:56:44 | <EvanR> | the dependency injection monad |
| 19:57:30 | <Rembane> | Enterprise Patterns for Haskell etc |
| 19:57:38 | <monochrom> | Abusing the (->) Functor, you can rewrite the functor law "fmap (f . g) = fmap f . fmap g" to "fmap (fmap f g) = fmap (fmap f) (fmap g)". >:) |
| 19:59:12 | <tomsmeding> | on a related note, if you want to fmap two functors deep, that's |
| 19:59:14 | <tomsmeding> | :t fmap fmap fmap |
| 19:59:15 | <lambdabot> | (Functor f1, Functor f2) => (a -> b) -> f1 (f2 a) -> f1 (f2 b) |
| 19:59:18 | <EvanR> | so if you don't want or need any IO, does that automatically make your app monad slower |
| 19:59:21 | <tomsmeding> | also known as fmap . fmap |
| 19:59:50 | <EvanR> | by implementing on the stuff IO does purely |
| 19:59:55 | <EvanR> | all the stuff |
| 20:00:36 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 260 seconds) |
| 20:01:00 | <tomsmeding> | IO as a monad is essentially just `State ()`, except that there's no runIO (that's unsafePerformIO, but it's marked unsafe for a good reason) so there's only one so we have control over it |
| 20:01:50 | <tomsmeding> | all the impure stuff in IO is just unsafely calling side-effecting primops and relying on the guarantees of being a monad for overall purity |
| 20:03:08 | <tomsmeding> | EvanR: if you don't build on IO, then you don't have IORefs |
| 20:03:40 | <tomsmeding> | that 'env' typically contains a bunch of IORefs, making you a makeshift state monad, except with the state in IORefs |
| 20:04:36 | <EvanR> | and instead of exceptions you have Either |
| 20:04:40 | <EvanR> | or Maybe |
| 20:05:58 | <tomsmeding> | the reason why Either for exceptions is slower than using IO exceptions (or asynchronous exceptions, for that matter) is that using Either entails a conditional branch at every >>= |
| 20:06:01 | <EvanR> | on the IORef front I was under the impression that mutable variables takes a hit thanks to the GC, compared to like, updating an IntMap of stuff |
| 20:06:05 | <tomsmeding> | and that's a lot of additional conditional branches |
| 20:06:21 | <tomsmeding> | and also, potentially, a bunch of additional allocation if the Right constructors don't get eliminated |
| 20:06:36 | <tomsmeding> | potentially |
| 20:06:46 | <tomsmeding> | I don't know enough about the performance details there :D |
| 20:07:08 | <tomsmeding> | I just know that I once converted an interpreter from using Either to using asynchronous exceptions, and it was multiple times faster |
| 20:07:19 | <tomsmeding> | I felt gross but I did it anyway |
| 20:07:37 | <EvanR> | clearly you should have used CPS or something |
| 20:07:41 | <tomsmeding> | perhaps |
| 20:08:30 | → | hugo joins (znc@verdigris.lysator.liu.se) |
| 20:09:01 | <EvanR> | so maybe ContT trumps all in performance |
| 20:09:37 | <tomsmeding> | I have indeed been told at some point that newtype Error e a = Error (forall r. (e -> r) -> (a -> r) -> r) is more performant than Either |
| 20:09:41 | × | Jackneill quits (~Jackneill@20014C4E1E021C00C8911A68759FC1A4.dsl.pool.telekom.hu) (Ping timeout: 255 seconds) |
| 20:10:16 | <EvanR> | hell yes |
| 20:10:27 | <EvanR> | well it deserves a benchmark I guess |
| 20:11:09 | → | Torio joins (~Torio@static-245-43-225-77.ipcom.comunitel.net) |
| 20:11:15 | × | takuan quits (~takuan@178-116-218-225.access.telenet.be) (Remote host closed the connection) |
| 20:11:30 | × | sm quits (~sm@plaintextaccounting/sm) (Quit: sm) |
| 20:12:04 | → | sm joins (~sm@plaintextaccounting/sm) |
| 20:12:22 | → | pretty_dumm_guy joins (trottel@gateway/vpn/protonvpn/prettydummguy/x-88029655) |
| 20:12:42 | × | sm quits (~sm@plaintextaccounting/sm) (Client Quit) |
| 20:12:49 | × | Inst quits (~Inst@120.244.192.250) (Ping timeout: 252 seconds) |
| 20:14:08 | × | Torio quits (~Torio@static-245-43-225-77.ipcom.comunitel.net) (Quit: Leaving) |
| 20:14:31 | <tomsmeding> | but if so, why does GHC not convert it for us? |
| 20:14:48 | <tomsmeding> | f :: Error e a -> Either e a ; f (Error g) = g Left Right |
| 20:14:54 | <tomsmeding> | it's not like it's difficult |
| 20:15:02 | <tomsmeding> | you can still pattern-match |
| 20:15:35 | × | hugo quits (znc@verdigris.lysator.liu.se) (Ping timeout: 240 seconds) |
| 20:15:54 | <tomsmeding> | ah, because in general that introduces recomputation |
| 20:16:04 | <tomsmeding> | you're now call-by-name instead of call-by-need |
| 20:16:52 | <tomsmeding> | it only works as a monad because the "carrier" of the monad (I have no idea how that is called; I mean the 'Error e a' value) is threaded linearly through the computation, so you always invoke the function at most once |
| 20:17:40 | <tomsmeding> | that linear threading is there for the same reason that mutability can work in a monadic context |
| 20:17:41 | <EvanR> | unless you do recursion? |
| 20:17:48 | <tomsmeding> | hm? |
| 20:18:02 | <EvanR> | you can come back to the same action in a monadic program |
| 20:18:08 | <tomsmeding> | can you? |
| 20:18:08 | × | idgaen quits (~idgaen@2a01:e0a:498:fd50:fcc6:bb5d:489a:ce8c) (Quit: WeeChat 4.0.5) |
| 20:18:16 | <tomsmeding> | do you mean with mfix? |
| 20:18:24 | <EvanR> | main = print "Hello World" >> main |
| 20:18:29 | <tomsmeding> | that's not the same action |
| 20:18:34 | <EvanR> | o_O |
| 20:18:36 | <tomsmeding> | that's a different action each time, generated by the same code |
| 20:18:49 | <EvanR> | it's a CAF |
| 20:18:56 | <EvanR> | right |
| 20:18:59 | <tomsmeding> | sure, it's the same code |
| 20:19:14 | <tomsmeding> | but like, 'foo x = Right (x + 1) >>= foo' |
| 20:19:28 | <tomsmeding> | or even without the +1 so that it's really the same action each time |
| 20:19:30 | <EvanR> | that wouldn't be the same since x is changing |
| 20:19:33 | <tomsmeding> | sure |
| 20:19:38 | <EvanR> | rather, it's an argument |
| 20:19:40 | <tomsmeding> | 'foo = Right () >> foo' |
| 20:19:42 | <tomsmeding> | now happy? :p |
| 20:19:51 | <EvanR> | yeah there's only one foo |
| 20:19:53 | <tomsmeding> | yes |
| 20:20:02 | <tomsmeding> | but the Either is threaded linearly through the infinite computation |
| 20:20:22 | <EvanR> | and there ought to be one Right () |
| 20:20:40 | <tomsmeding> | there's a Right (), which gets case-analysed in (>>), then the result ( () ) gets destroyed in this case and we continue with foo |
| 20:20:51 | <tomsmeding> | you don't case-analyse the same Either multiple times |
| 20:20:58 | <tomsmeding> | you create a new one each time before case-analysing it |
| 20:21:08 | <EvanR> | that doesn't seem right |
| 20:21:22 | <tomsmeding> | not after optimisations, of course |
| 20:21:29 | <tomsmeding> | naively |
| 20:21:42 | <tomsmeding> | I'm not talking about machine implementation here, I'm talking about semantics |
| 20:21:46 | <EvanR> | naively, foo is a single graph fragment not a function body |
| 20:21:49 | <tomsmeding> | call-by-name vs call-by-need vs call-by-value |
| 20:22:02 | <EvanR> | oh, you lost me there xD |
| 20:22:41 | <tomsmeding> | I mean the point is that if you do this: let Error g = ... in g a b + g c d + g e f |
| 20:22:46 | <EvanR> | call-by-whatever sounds more implementationy than the graph story |
| 20:22:49 | <tomsmeding> | then you're calling g multiple times |
| 20:23:28 | <tomsmeding> | whereas if you 'let e :: Either _ _ = ... in (case e of Left x -> a x ; Right y -> b y) + (case e of Left x -> c x; Right y -> d y) + ...' |
| 20:23:48 | <tomsmeding> | then you don't evaluate e multiple times, you evaluate it _once_ |
| 20:23:59 | <tomsmeding> | the latter thing is what you want in call-by-need |
| 20:24:17 | <tomsmeding> | with the 'let Error g = ...' example you get call-by-name: every use of the variable recomputes its definition |
| 20:24:21 | <tomsmeding> | that's complete crap |
| 20:24:34 | <tomsmeding> | the reason Error works as a monad is that you _never_ case-analyse the same thing multiple times |
| 20:24:42 | <EvanR> | yeah you usually wouldn't do that g ab + g c d + g e f thing with monadic code, but you would possible recurse back to the same action |
| 20:24:44 | <tomsmeding> | the only time you case-analyse it is when passing it to >>= |
| 20:25:11 | <tomsmeding> | you _can't_ do that g a b + g c d + g e f thing with monad code precisely because of what I'm trying to say XD |
| 20:25:17 | <tomsmeding> | that's the point |
| 20:25:25 | <tomsmeding> | why Error works as a monad and not as an alternative Either |
| 20:25:30 | <EvanR> | yeah usually might be too conservative |
| 20:25:42 | <EvanR> | but you could recurse back to the same action |
| 20:26:02 | <tomsmeding> | and then you might case-analyse the result again |
| 20:26:12 | <tomsmeding> | but at that point the pure contents of the Right has already been evaluated |
| 20:26:15 | <tomsmeding> | it won't be evaluated again |
| 20:26:19 | <tomsmeding> | with the CPS version, it would |
| 20:27:28 | <EvanR> | unless the thing being returned from the Error function was in a closure and somehow arranged to be evaluated once only |
| 20:27:38 | <tomsmeding> | sure |
| 20:28:08 | × | dumptruckman quits (~dumptruck@143-42-184-47.ip.linodeusercontent.com) (Quit: ZNC - https://znc.in) |
| 20:28:25 | → | eggplantade joins (~Eggplanta@2600:1700:38c5:d800:e9d7:8bce:4928:5b34) |
| 20:28:36 | <tomsmeding> | but in general, to get to that point you either have to do some actual work (in putting lambdas in the right spot), or to rely on hoisting by GHC, which is an optimisation |
| 20:28:59 | <EvanR> | so the story I'm gathering is constructors are slow dumb and easy, CPS is fast advanced and tricky |
| 20:29:01 | × | wootehfoot quits (~wootehfoo@user/wootehfoot) (Read error: Connection reset by peer) |
| 20:29:07 | <tomsmeding> | ... kinda? |
| 20:29:34 | <tomsmeding> | CPS works well when you're tail-calling all the time |
| 20:29:43 | <tomsmeding> | as soon as you don't, you have to watch out |
| 20:29:46 | → | machinedgod joins (~machinedg@d198-53-218-113.abhsia.telus.net) |
| 20:30:01 | <tomsmeding> | this conversation is weird |
| 20:30:23 | <tomsmeding> | I started out not understanding something, then understanding it anyway a minute later, then spending a screenful of convo to try to explain what I just understood |
| 20:30:52 | <tomsmeding> | more than a screenful |
| 20:30:59 | → | dumptruckman joins (~dumptruck@23-239-13-136.ip.linodeusercontent.com) |
| 20:31:55 | × | _ht quits (~Thunderbi@28-52-174-82.ftth.glasoperator.nl) (Quit: _ht) |
| 20:32:12 | <EvanR> | and IO might be simpler and faster than everything |
| 20:32:20 | <EvanR> | sad state of affairs if true |
| 20:32:37 | <tomsmeding> | functional programming was not invented for performance |
| 20:33:30 | × | michalz quits (~michalz@185.246.207.197) (Remote host closed the connection) |
| 20:37:51 | → | hugo- joins (znc@verdigris.lysator.liu.se) |
| 20:38:34 | × | emmanuelux_ quits (~emmanuelu@user/emmanuelux) (Quit: au revoir) |
| 20:40:49 | <cpressey> | I have an immensely hard time wrapping my head around so many of the things that have been said in this channel this evening |
| 20:41:16 | <cpressey> | There's a temptation to pick one, and ask "what do you mean by that"? |
| 20:41:31 | <EvanR> | lets at least hope it's mostly not wrong |
| 20:42:04 | <Rembane> | cpressey: Do it! If you're lucky you'll get an answer! :D |
| 20:42:07 | <tomsmeding> | cpressey: how many of those things have been said by me |
| 20:42:14 | <EvanR> | when it comes to trying to get the most performance out of haskell, I found it gets crazy fast |
| 20:42:37 | <tomsmeding> | amen |
| 20:42:39 | <EvanR> | but if the answer is "just do env -> IO a" then that's actually pretty simple and good |
| 20:42:51 | <tomsmeding> | iirc, in practice, kind of yes |
| 20:42:58 | <tomsmeding> | if you want effectful code |
| 20:43:21 | <tomsmeding> | for pure code that doesn't need monads in the first place, there's a whole other, orthogonal load of tricks and magic that you can use to make things faster |
| 20:43:45 | → | Carbon-lang joins (~Carbonlan@ip121.ip-149-56-160.net) |
| 20:43:54 | <cpressey> | See, things like "pure code that doesn't need monads" |
| 20:44:03 | <tomsmeding> | vague handwaving |
| 20:44:22 | <tomsmeding> | 99% of actual facts about performant code depend on the precise circumstance |
| 20:44:32 | × | Carbon-lang quits (~Carbonlan@ip121.ip-149-56-160.net) (Client Quit) |
| 20:44:33 | <tomsmeding> | so if you try to abstract over that, it gets vague fast |
| 20:44:46 | <tomsmeding> | if you pass around a few Eithers here and there, is that monadic code? hardly |
| 20:44:54 | <tomsmeding> | but if you do it enough, it might start to look like it |
| 20:45:20 | × | oo_miguel quits (~Thunderbi@78-11-179-96.static.ip.netia.com.pl) (Ping timeout: 255 seconds) |
| 20:45:28 | <cpressey> | If you use Either as a monad, that's monadic code, isn't it? |
| 20:45:41 | <tomsmeding> | luckily I said "orthogonal", because the "pure code tricks" apply always, and the monad tricks apply only if you're in a monad :D |
| 20:45:45 | <tomsmeding> | yes |
| 20:45:48 | → | lortabac joins (~lortabac@2a01:e0a:541:b8f0:263b:38d2:5b76:172d) |
| 20:45:49 | × | lortabac quits (~lortabac@2a01:e0a:541:b8f0:263b:38d2:5b76:172d) (Client Quit) |
| 20:45:59 | <tomsmeding> | that's actually an important example that we've been discussing |
| 20:46:25 | <tomsmeding> | but if you inline all the >>=s from Either and do the case analyses manually, is that monadic code? |
| 20:46:36 | <tomsmeding> | GHC doesn't really see the difference after a few inlining passes |
| 20:48:01 | <cpressey> | I assume by "inline >>=" you mean "expand >>= to its definition"? |
| 20:48:04 | <tomsmeding> | yeah |
| 20:48:47 | <cpressey> | Yeah, I don't know, if I write 4+4+4+4+4, am I doing multiplication? |
| 20:48:55 | <tomsmeding> | not really |
| 20:49:26 | <tomsmeding> | but for the purpose of optimisation, there's little difference between code using (>>=) from EIther and code that uses its expanded definition |
| 20:49:41 | × | fendor quits (~fendor@2a02:8388:1640:be00:aab:1226:f274:5021) (Remote host closed the connection) |
| 20:50:23 | <tomsmeding> | what is "monadic code" in this context is hard to put one's finger on without punting to "whatever is the set of circumstances where this particular change to the code's structure improves performance" |
| 20:50:28 | <tomsmeding> | which is as uninformative as it gets |
| 20:50:29 | <EvanR> | pure code and pure data is kind of haskell street jargon, a pure function is one which has no side effects and only depends on the input |
| 20:50:31 | <cpressey> | OK, never mind, the levels on which you are thinking about these concepts, are not the same levels I am thinking about them on. Which is fine |
| 20:50:58 | <EvanR> | there's some kind of correlation between pure functions and pure other stuff that I never figured out, so it's probably bogus |
| 20:51:17 | <tomsmeding> | it's trying to abstract over things that don't _really_ allow abstracting over, because they're really more complex |
| 20:51:31 | <tomsmeding> | I don't really know, but suspect, that you're firmly in that land where things are more complex |
| 20:51:48 | <tomsmeding> | I've been trying to obstinately abstract anyway in order to extract some general guidelines |
| 20:51:49 | <EvanR> | monadic code and pure code is probably a bad distinction to try to draw |
| 20:52:15 | <tomsmeding> | it may be a helpful one for abstracting over certain classes of programs |
| 20:52:21 | <cpressey> | "Haskell street jargon", I like that. |
| 20:52:31 | <tomsmeding> | to learn a lesson about optimisation _once_ instead of again every time |
| 20:52:40 | <tomsmeding> | oh it's all street jargon for sure |
| 20:52:43 | <cpressey> | There is monadic code that is perfectly "pure" in the sense that it has no side effects. |
| 20:53:02 | <cpressey> | So to contrast "monadic" against "pure" seems to miss something. |
| 20:53:07 | <EvanR> | even IO code has no side effects, until it gets executed |
| 20:53:31 | <tomsmeding> | coming back to what dolio taught me earlier this evening: the definition of the words "pure", "monadic", etc. depend on context :D |
| 20:53:38 | <tomsmeding> | "effectful" |
| 20:54:32 | <tomsmeding> | is code using the Either monad pure? monadic? effectful? |
| 20:54:48 | <EvanR> | yes, yes, yes |
| 20:54:51 | <tomsmeding> | what if you expand >>= to its definition? |
| 20:54:58 | <tomsmeding> | EvanR: lol |
| 20:55:03 | <tomsmeding> | thank you |
| 20:55:30 | <tomsmeding> | the answers to these questions depend on what you're going to do with those answers |
| 20:55:35 | <EvanR> | the effects are directly modeled in the code rather than using magic beans |
| 20:56:00 | <tomsmeding> | you _can_ make these things precise, but sometimes that's very hard or even counterproductive |
| 20:56:10 | <cpressey> | I was going to say, Either can be defined entirely in Haskell; but IO (and others) can't. |
| 20:56:26 | <tomsmeding> | because they rely on GHC primitives? |
| 20:56:30 | <EvanR> | you can make something like IO with normal haskell, which is kind of where free monads live |
| 20:56:32 | <tomsmeding> | are they not Haskell? |
| 20:56:37 | <cpressey> | GHC is an implementation detail |
| 20:56:40 | <tomsmeding> | add "Haskell" to the list :D |
| 20:57:03 | <EvanR> | IO is abstract just because reasons, it could've had the primitives defined as constructors and exposed |
| 20:57:10 | → | Inst joins (~Inst@120.244.192.250) |
| 20:57:26 | <EvanR> | and the runtime interleaves execution with the followup computation either way |
| 20:57:35 | <tomsmeding> | cpressey: distinguishing Either from IO based on whether they can be defined in, say, Haskell2010 is a useful distinction sometimes |
| 20:57:42 | <tomsmeding> | it's not a useful distinction other times |
| 20:57:51 | <Inst> | so, about my issue with liftA2 having unpredictable order of effects, I guess the conclusion is: |
| 20:58:00 | <cpressey> | tomsmeding: Om |
| 20:58:09 | <Inst> | If a monad instance exists, the monad laws binding the applicative instance to monad means that the order of effects is predictable |
| 20:58:22 | <Inst> | if it doesn't exist, then there's more of a problem |
| 20:58:28 | <tomsmeding> | not more of a problem |
| 20:58:34 | <EvanR> | I thought Applicative also had an order of effects, or am I late to this party |
| 20:58:39 | <tomsmeding> | you just don't get a guarantee |
| 20:58:39 | <Inst> | well, just understand the applicative then |
| 20:58:41 | <tomsmeding> | EvanR: not from the laws |
| 20:58:47 | <tomsmeding> | from the Monad laws you get an order |
| 20:58:58 | <Inst> | also, I was sort of besotted with liftA2, iirc, it wasn't in Prelude for a while? |
| 20:59:12 | <tomsmeding> | ¯\_(ツ)_/¯ |
| 20:59:19 | <Inst> | turns out it's easier to use foo <$> bar <*> baz because you can verticalize it more easily |
| 20:59:36 | <Inst> | looks way better, fits better if you're binding the result into something within do, etc |
| 20:59:37 | → | Pozyomka joins (~pyon@user/pyon) |
| 20:59:39 | <EvanR> | verticalization is not street jargon I know |
| 21:00:21 | <tomsmeding> | liftA2 foo bar |
| 21:00:21 | <tomsmeding> | baz |
| 21:00:37 | <EvanR> | good shot |
| 21:00:49 | tomsmeding | . o O ( https://esolangs.org/wiki/Fish ) |
| 21:00:51 | <Inst> | yeah but operators starting lines is a fairly common style |
| 21:01:05 | <dolio> | Applicatives have ordering. It's the order you write them in. |
| 21:01:25 | <dolio> | Applicatives are list-alike, and lists are ordered. |
| 21:01:54 | <Inst> | Concurrently, i.e, when the result comes back is unknown? |
| 21:02:05 | <tomsmeding> | dolio: the Applicative laws don't give guarantees about whether the effects of foo are evaluated before bar, or the other way round, in 'foo <*> bar', right? |
| 21:02:44 | <monochrom> | I don't think "Applicative is ordered" or "Applicative is unordered" has any meaning. |
| 21:03:07 | <monochrom> | If you know the actual instance, e.g., IO, then talk about it directly. |
| 21:03:21 | <tomsmeding> | and if you don't? |
| 21:03:45 | <monochrom> | Things like Tardis have shown that "order" is a tricky notion, even for Monad. |
| 21:04:02 | <tomsmeding> | hm, fair |
| 21:04:08 | <tomsmeding> | also Cont |
| 21:04:24 | <dolio> | Applicatives let you arrange things in sequences. What those sequences mean is open. |
| 21:04:37 | <monochrom> | And by the time it's Reader or (->), it's vanilla lazy evaluation again. |
| 21:05:30 | <EvanR> | <*> is infixl, : is infixr. So it's in the opposite order of list? |
| 21:05:36 | <dolio> | What monads add is nesting. f inside f instead of f beside f. |
| 21:06:22 | <tomsmeding> | EvanR: that's opposite associativity |
| 21:06:37 | <monochrom> | To the extent that the Applicative laws alone don't have a commutative law for liftA2, we agree. |
| 21:07:00 | <monochrom> | But some instances can have commutative laws or conditional commutative laws. |
| 21:07:33 | <Inst> | dolio: more, the ability to work with nesting |
| 21:07:36 | <tomsmeding> | it's funny talking about "order of effects" in Applicatives when the whole point about Applicative is that you explicitly get no language for talking about said order |
| 21:07:41 | <Inst> | join / flatten / mu |
| 21:07:46 | <monochrom> | Stepping back, this is what's wrong with using "plain English" to discuss programming. |
| 21:08:10 | <monochrom> | "order" has like a million unrelated meanings. |
| 21:08:35 | <dolio> | Lists aren't ordered. Only trees are ordered. |
| 21:09:15 | <EvanR> | > compare [1,2,3] [2,3,4] |
| 21:09:17 | <lambdabot> | LT |
| 21:09:52 | <EvanR> | > compare [1 :+ 1] [2 :+ 2] |
| 21:09:53 | <lambdabot> | error: |
| 21:09:53 | <lambdabot> | • No instance for (Ord (Complex Integer)) |
| 21:09:53 | <lambdabot> | arising from a use of ‘compare’ |
| 21:09:56 | <EvanR> | nvm |
| 21:10:05 | <EvanR> | lists aren't ordered |
| 21:10:10 | <monochrom> | Hell, s/to discuss programming// >:) |
| 21:10:52 | <tomsmeding> | monochrom: matches with a remark you made previously about people ;) |
| 21:11:03 | <EvanR> | plain English is doomed to failure. From now on we will only speak shakespearean |
| 21:11:13 | <tomsmeding> | Lojban |
| 21:11:26 | <Inst> | [whamlet|<p> Hello, world!</p>|] |
| 21:11:35 | <darkling> | EvanR: I believe you mean "henceforth", varlet! |
| 21:11:38 | <Inst> | oh, whoops |
| 21:12:15 | <Inst> | [whamlet|<p> To be, or not to be, that is the question </p>|] |
| 21:13:46 | <monochrom> | And reflecting to last night's conversation about type classes and their instances and their methods, a key point is that there are now two "membership" relations, not just one. If you assume just one, that explains getting confused. |
| 21:13:57 | <monochrom> | (All confusions are caused by wrong assumptions.) |
| 21:14:12 | × | cpressey quits (~cpressey@host-92-10-148-105.as13285.net) (Quit: Client closed) |
| 21:14:39 | <monochrom> | On one side, one membership relation is "Int is an instance of Eq". On the other side, the 2nd membership relation is "(==) is a method of Eq". |
| 21:15:12 | <jumper> | how and where would I use the bind operator? >>=, If I understood correctly, X >>= Y, X is bound to Y |
| 21:15:27 | <monochrom> | Until you accept that even in UML you can draw such a two-side diagram, harping the "plain English" word "member" is not going to help. |
| 21:16:13 | <monochrom> | You can use it like "getLine >>= putStrLn". |
| 21:16:31 | <monochrom> | It reads a line from stdin, then outputs it to stdout. |
| 21:16:54 | <jumper> | Wait, so it's simply an pipe? |
| 21:17:03 | <EvanR> | >> is an IO action combiner, sequentially combining two actions. But the first result is discarded |
| 21:17:09 | <dolio> | It's like reverse function application. |
| 21:17:10 | <EvanR> | >>= lets you use the first result |
| 21:17:24 | <monochrom> | It can do much more. That was just a basic example. |
| 21:17:54 | <dolio> | 'bind' presumably comes from the use where you do `m >>= \x -> ...`, where you're "binding" the result of m to the variable x. |
| 21:18:08 | <jumper> | But isn't getLine >>= putStrLn == putStrLn getLine ? |
| 21:18:15 | <EvanR> | it is not |
| 21:18:21 | <dolio> | The latter is a type error. |
| 21:18:24 | <Inst> | the latter is a type error |
| 21:18:29 | <monochrom> | It may or may not surprise you that [1,2,3] >>= replicate 5 can also have a meaning. |
| 21:19:05 | <EvanR> | :t putStrLn |
| 21:19:06 | <lambdabot> | String -> IO () |
| 21:19:18 | <monochrom> | And with "plain human speak" being so bloody bendable, you may even call it "piping". |
| 21:19:27 | <monochrom> | > [1,2,3] >>= replicate 5 |
| 21:19:28 | <lambdabot> | [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3] |
| 21:19:47 | <jumper> | haskell: getLine >>= putStrLn, C: puts(gets()); |
| 21:20:03 | × | __monty__ quits (~toonn@user/toonn) (Quit: leaving) |
| 21:20:06 | <monochrom> | Well this is where C is sloppy and Haskell is more precise. |
| 21:20:26 | <EvanR> | putStrLn takes a String, not a function or an IO action |
| 21:20:26 | <monochrom> | "puts(gets())" is not supposed to make sense. |
| 21:20:31 | <Inst> | Which book are you working with again? |
| 21:20:33 | <monochrom> | At least, IMO. |
| 21:21:03 | <jumper> | monochrom: what you mean? I perfectly understand the nesting logic |
| 21:21:04 | <monochrom> | To be sure I have a selection bias. There is a reason I joined the Haskell community! |
| 21:21:16 | <EvanR> | jumper, do you understand the type mismatch |
| 21:21:46 | ← | rawles parts (~rawles@user/rawles) (Textual IRC Client: www.textualapp.com) |
| 21:21:49 | <jumper> | EvanR: similar to datatype mismatches in C? |
| 21:22:04 | <monochrom> | Oh all of us understand the flawed logic of C or even in general of imperative programming. |
| 21:22:11 | <monochrom> | Doesn't mean we have to agree with it. |
| 21:22:31 | <EvanR> | you said putStrLn getLine, for that to work the type of getLine has to match the input type of function putStrLn |
| 21:22:38 | <monochrom> | I understand why thieves steal. They are still wrong. |
| 21:22:47 | <jumper> | EvanR: can I cast it? :) |
| 21:22:52 | <Inst> | :t getLine |
| 21:22:53 | <lambdabot> | IO String |
| 21:22:59 | <EvanR> | no and that's often wrong in C too |
| 21:23:13 | × | acidjnk_new quits (~acidjnk@p200300d6e72b933890137bb0a9c5386a.dip0.t-ipconnect.de) (Ping timeout: 252 seconds) |
| 21:23:33 | <EvanR> | it's like can I melt my lego bricks when they don't fit |
| 21:24:01 | <EvanR> | yes but it takes so much heat you burn yourself |
| 21:24:07 | <jumper> | does Haskell support void pointers? |
| 21:24:15 | <geekosaur> | jumper, if you're thinking in terms of casting then you're not getting it |
| 21:24:32 | <geekosaur> | really, do not try to treat Haskell as funny looking C, it won't work |
| 21:24:42 | <monochrom> | What do you need void pointers for? |
| 21:24:53 | <geekosaur> | @where cis194 |
| 21:24:53 | <lambdabot> | <https://github.com/byorgey/haskell-course>,<https://www.seas.upenn.edu/~cis194/spring13/lectures.html> |
| 21:25:12 | <monochrom> | C offered them because C didn't have genericity. We can now do better. See Rust for example. |
| 21:25:28 | <Inst> | iirc, C / C++ experience, right? |
| 21:25:41 | <geekosaur> | it has to be like C or Python |
| 21:25:49 | <monochrom> | Yeah even in C++ you don't need void pointer any more. |
| 21:25:54 | <geekosaur> | jumper can't understand anything else, apparently |
| 21:26:03 | <Inst> | I think jumper said they learned C++11 via implementing it by C. |
| 21:26:14 | <Inst> | That has to be respected, because it's a hardcore way of learning C++ |
| 21:26:15 | <jumper> | Inst: self learning |
| 21:26:23 | <EvanR> | implement haskell in C |
| 21:26:46 | <mauke> | one of the IOCCC winners is a haskell compiler :-) |
| 21:26:55 | <monochrom> | Perhaps read Hugs source code? It's a Haskell interpreter written in C. |
| 21:27:03 | <monochrom> | Hahaha that's epic. |
| 21:27:53 | <monochrom> | If pressed, I could write a toy Haskell implementation in C, but not to the point of meeting the IOCCC standard so that even I don't understand it. >:) |
| 21:28:44 | <Inst> | is this canonical? |
| 21:28:46 | <Inst> | https://github.com/haskell-implementations/hugs |
| 21:28:51 | <mauke> | jumper: are you familiar with javascript or promises/futures? |
| 21:29:32 | <jumper> | mauke: I haven't touched interpreted languages since python, JS background none existant, but I understand the syntax |
| 21:29:42 | <monochrom> | Inst: I think yes. |
| 21:30:09 | <EvanR> | if you only understand the concrete syntax of javascript, you don't understand javascript. Because it uses C syntax |
| 21:30:12 | <monochrom> | Oooohhhh this is going to be fun... |
| 21:30:29 | <monochrom> | Is math invented or discovered? Is Haskell compiled or interpreted? >:) |
| 21:31:11 | <EvanR> | languages keep using C syntax while being wildly different in various ways |
| 21:31:12 | <mauke> | is it possible to exceed the speed of c in a relativistic universe? |
| 21:31:27 | <EvanR> | different from C semantics |
| 21:31:33 | <monochrom> | Is it a half-empty glass or a half-full glass? Or is it half-empty and the other half is not even the right drink? >:) |
| 21:31:47 | <monochrom> | @quote monochrom speed |
| 21:31:47 | <lambdabot> | monochrom says: And so, I use formal logic all the time, and can still be very practical and speedy. This is contrary to most people's conventional wisdom. This is because they have only seen very |
| 21:31:47 | <lambdabot> | primitive formal logics, like if you have only seen assembly code, you think programming is undoable. |
| 21:31:51 | <monochrom> | err no |
| 21:31:55 | <monochrom> | @quote monochrom faster.than |
| 21:31:55 | <lambdabot> | monochrom says: einstein's theory implies that haskell cannot be faster than c |
| 21:32:49 | <Inst> | jumper, but, sorry, just want a bit more information, which book / course are you using to pick up Haskell? |
| 21:33:03 | <jumper> | Inst: none |
| 21:33:11 | <mauke> | jumper: sadly that doesn't give you the right mindset for a shortcut to IO semantics |
| 21:33:50 | <jumper> | Inst: reading Haskell documentation is usually the best source |
| 21:34:28 | <mauke> | conversely, reading Haskell source is often the best available documentation :-( |
| 21:34:36 | <Inst> | Wow, got to admire your courage. |
| 21:34:44 | <monochrom> | Wait, new Data.Functor has an unzip?! |
| 21:34:58 | <EvanR> | :t unzip |
| 21:34:59 | <lambdabot> | [(a, b)] -> ([a], [b]) |
| 21:35:09 | × | phma quits (~phma@host-67-44-208-16.hnremote.net) (Read error: Connection reset by peer) |
| 21:35:30 | <EvanR> | Functor f => f (a,b) -> (f a, f b)? |
| 21:35:34 | → | phma joins (~phma@2001:5b0:210d:ff48:373f:c0e:f95b:a8f5) |
| 21:35:46 | <monochrom> | unzip :: Functor f => f (a, b) -> (f a, f b) |
| 21:35:54 | <monochrom> | Yeah. Interesting. |
| 21:35:55 | <Inst> | jumper; what do you mean by Haskell source? |
| 21:36:07 | <EvanR> | slowly we approach categorical linear algebra |
| 21:37:09 | <EvanR> | I'm surprised because unzip is one of those functions I would expect people to say don't generalize think of the noobs |
| 21:37:10 | <jumper> | Inst: Haskell wiki? Haskell.org? |
| 21:37:35 | <jumper> | Inst: The same way you learn assembler, manuals |
| 21:37:51 | <monochrom> | Prelude's unzip is still the list one. |
| 21:38:03 | <EvanR> | oh ok |
| 21:38:09 | <EvanR> | noobs protected |
| 21:38:52 | <Inst> | The problem with that is that you usually want to understand at least 50-60% of what you're reading |
| 21:39:08 | <Inst> | then try to guess the meaning of at least 30% of the remainder |
| 21:39:14 | <Inst> | if you start with insufficient reference points, it's much harde |
| 21:39:15 | <Inst> | *r |
| 21:39:26 | <EvanR> | Inst, are you trying to argue against reading haskell documentation |
| 21:39:34 | <EvanR> | is this a Nick thing again |
| 21:39:43 | <jumper> | Inst: sure, but that's where small examples come in, semantic dissection |
| 21:39:58 | <mauke> | :t (,) <$> (fst <$>) <*> (snd <$>) |
| 21:39:59 | <lambdabot> | Functor f => f (b1, b2) -> (f b1, f b2) |
| 21:40:26 | <Inst> | what i really want to ask is, how far do you understand typeclasses? |
| 21:40:48 | <monochrom> | 99.9% of such small examples and hypotheses can be trivially tested on ghci and you need no human to help. |
| 21:41:03 | → | acidjnk_new joins (~acidjnk@p200300d6e72b933890137bb0a9c5386a.dip0.t-ipconnect.de) |
| 21:42:13 | <Inst> | but if you're going that approach: |
| 21:42:14 | <Inst> | https://downloads.haskell.org/ghc/latest/docs/users_guide/ |
| 21:42:25 | <jumper> | Already reading it |
| 21:42:31 | <mauke> | https://www.haskell.org/onlinereport/haskell2010/ if you're hardcore |
| 21:42:31 | <Inst> | https://www.haskell.org/onlinereport/haskell2010/ |
| 21:43:12 | <monochrom> | The GHC User's Guide assumes that you already know Haskell. |
| 21:43:18 | <EvanR> | https://www.haskell.org/tutorial/ >:) |
| 21:43:23 | <tomsmeding> | none of these resources teach you functional programming |
| 21:43:37 | <mauke> | EvanR: hah, exactly what I expected behind that url :-) |
| 21:43:49 | → | Vajb joins (~Vajb@207.61.167.122) |
| 21:43:53 | <tomsmeding> | ah the tutorial might, though iirc "gentle" is not quite accurate |
| 21:43:54 | <Inst> | no, but it's really impressive if he can pull it off and just learn some dialect of Haskell from the docs alone |
| 21:43:59 | <monochrom> | I did learn from the Gentle Introduction. |
| 21:44:14 | <monochrom> | Actually I found it gentle too. |
| 21:44:31 | <tomsmeding> | the language specification and the GHC user's guide are very bad places to start if you've never done any functional programming |
| 21:44:37 | <monochrom> | Sure, if you have presumptions and prejudice, it is not gentle. |
| 21:44:53 | tomsmeding | has never read the "gentle introduction" |
| 21:45:05 | <tomsmeding> | so no opinion there |
| 21:45:11 | <monochrom> | But in the same way, if you make FP presumptions then go learn C, no C tutorial will be gentle either. |
| 21:45:27 | <Inst> | EvanR: I just was scared for jumper, but he seems really hardcore, learned C++ by implementing it via C, and now he wants to learn Haskell from the Haskell Report |
| 21:45:41 | <tomsmeding> | that ain't going to work |
| 21:45:41 | <EvanR> | I have no issue with the haskell report |
| 21:45:50 | <Inst> | Let him try |
| 21:45:56 | <Inst> | if he succeeds, he's a hero, let's celebrate him |
| 21:45:57 | <EvanR> | some people just like reading the material |
| 21:46:11 | <EvanR> | and don't need training wheels, or NeoHaskell, or whatever |
| 21:46:14 | <Inst> | if he fails, let's patch him up |
| 21:46:45 | <EvanR> | I wish other languages had a report |
| 21:46:51 | <mauke> | I learned C++ by reading The C++ Programming Language front to back |
| 21:46:54 | <dolio> | I think the gentle introduction kind of assumes you're already somewhat familiar with functional programming. |
| 21:47:00 | <dolio> | And it says so. |
| 21:47:03 | <mauke> | sadly it's all out of date now :-) |
| 21:47:04 | <EvanR> | yes |
| 21:47:05 | <Inst> | mauke: really? |
| 21:47:09 | <monochrom> | :( |
| 21:47:34 | <monochrom> | https://www.vex.net/~trebla/humour/programming_books.html >:) |
| 21:47:40 | <EvanR> | A gentle introduction assumes some exposure to functional programming already, and is somewhat out of date |
| 21:47:41 | <mauke> | Inst: pretty much, but I'd seen some examples of C++ features before |
| 21:48:07 | <EvanR> | and the CSS + banner image are not attractive! |
| 21:48:13 | <EvanR> | critical issues |
| 21:49:27 | × | acidjnk_new quits (~acidjnk@p200300d6e72b933890137bb0a9c5386a.dip0.t-ipconnect.de) (Ping timeout: 240 seconds) |
| 21:50:59 | <mauke> | if you know how C++ vtables are implemented (or can be implemented in C), then typeclasses as dictionary passing shouldn't be all that unfamiliar |
| 21:53:11 | × | machinedgod quits (~machinedg@d198-53-218-113.abhsia.telus.net) (Ping timeout: 260 seconds) |
| 21:54:46 | <jumper> | EvanR: yeah I got it, functions calls in haskell don't really work the same way as in C |
| 21:56:18 | <mauke> | true, but unrelated to the putStrLn getLine thing. that really is just a type mismatch |
| 21:56:43 | <EvanR> | putStrLn wants a String but getLine is not a String, it's an IO action |
| 21:57:01 | <Inst> | https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3 <-- typeclasses |
| 21:57:11 | <mauke> | it's semi-analogous to puts(gets) in C, but the difference is that C has (or at least had :-) a gets function that you could actually call |
| 21:57:15 | <Inst> | >>= is defined in a typeclass |
| 21:57:30 | <mauke> | getLine isn't a function at all |
| 21:57:31 | <EvanR> | Inst, I don't think anyone was asking about type classes today |
| 21:58:00 | <EvanR> | you can consider >>= to be an IO combiner for the purposes of getLine >>= putStrLn |
| 21:58:00 | <Inst> | yeah, i'll back off |
| 22:04:50 | <jumper> | mauke: you would be passing the address of gets function into puts in that case which wasn't what I ment. gets in this case could be a function which reads input and saves it into a buffer and returns a pointer to that buffer. Since in C, strings are simply arrays closed of with NULL bytes, addresses are used to point to said char array. |
| 22:05:27 | × | Vajb quits (~Vajb@207.61.167.122) (Ping timeout: 240 seconds) |
| 22:05:31 | <moni_> | "learning Haskell from the Haskell Report" reminds me of when I was 19 and decided I would learn programming fundamentals by going through The Art Of Computer Programming |
| 22:05:44 | <jumper> | moni_: hardcore |
| 22:06:28 | <mauke> | jumper: yes, that's exactly what I meant |
| 22:06:30 | <EvanR> | structure and interpretation of computer programming, though it's is not very haskell |
| 22:06:30 | <moni_> | A little too hardcore lmao, I spent a weekend doing nothing but the problems on chapter 1 and went "yeah no" lmao |
| 22:06:45 | <monochrom> | I think I did learn the "docker run" command from the docker-run CLI reference. :) |
| 22:06:50 | <EvanR> | er, computer programs |
| 22:07:41 | <mauke> | jumper: puts(gets) is wrong (a type error) because you're passing the gets operation itself (or in the case of C: a pointer to the function), not the result of reading input |
| 22:07:55 | <monochrom> | "structure and interpretation of computer programming" would be social commentary on programmer behavious. >:) |
| 22:08:01 | <jumper> | mauke: nested function calls in C are evaluated first before their return values are passed down as args to the next function |
| 22:08:19 | <monochrom> | Or, unstructure and misinterpretation >:) |
| 22:08:31 | <mauke> | I like turtles |
| 22:08:31 | <EvanR> | gets by itself evaluates to a pointer, it doesn't execute any I/O |
| 22:08:44 | × | gehmehgeh quits (~user@user/gehmehgeh) (Quit: Leaving) |
| 22:08:55 | <EvanR> | luckily it's a type error |
| 22:09:00 | → | euleritian joins (~euleritia@dynamic-046-114-207-017.46.114.pool.telefonica.de) |
| 22:09:04 | <monochrom> | Oh hey we used to call our 3rd-year-level computability-and-complexity course "effective and efficient computing". |
| 22:09:04 | <EvanR> | in puts(gets) |
| 22:09:46 | <mauke> | (except for the one time when gcc somehow didn't type-check I/O functions and you could do stuff like fgetc(), which would crash at runtime) |
| 22:09:54 | <monochrom> | But since it delivers bad news such as "this one is not computable, that one we can't do better than exp time yet", I think of it as "ineffective and inefficient computing". |
| 22:10:28 | <EvanR> | computer science the science of what you can't do |
| 22:10:35 | <monochrom> | Then I told that to a prof, and he said "my brother (another prof elsewhere) says defective and defficient computing" >:D |
| 22:11:33 | <EvanR> | the worst part is when the manager asks you to do something that is technically undecidable, you still can't use that as an excuse |
| 22:11:58 | <EvanR> | someone else will silently change the question just in time to not get fired |
| 22:12:06 | <jumper> | EvanR: when I pass a function, inside a function, if I use said function inside the function, could it be analogically said though that a Function pointer was passed down as an argument? |
| 22:12:56 | <EvanR> | ideally you put the function pointer in the actual type signature making that question redundant |
| 22:13:14 | <EvanR> | and helping the compiler help you do it right |
| 22:13:23 | <monochrom> | sin(arccos(x)) does not pass function pointers. In both C and Haskell. |
| 22:13:50 | <mauke> | jumper: in Haskell? sort of, but the "pointerness" is not apparent anywhere. since you can't do pointery things, it doesn't really make sense to talk about pointers |
| 22:13:51 | × | gooba quits (~gooba@90-231-13-185-no3430.tbcn.telia.com) (Remote host closed the connection) |
| 22:13:59 | <mauke> | also, this applies to all arguments, not just functions |
| 22:14:01 | <monochrom> | But "getLine :: IO String" is genuinely something new that has no analog in C or C++. |
| 22:14:26 | <monochrom> | But read on with the Haskell Report and take it seriously. |
| 22:14:35 | <EvanR> | regardless, the types don't match so the computer refuses to go |
| 22:14:39 | <mauke> | also, C only has "static" functions (defined at the top level) |
| 22:14:52 | <mauke> | in Haskell you can dynamically create functions at runtime |
| 22:14:53 | → | gooba joins (~gooba@90-231-13-185-no3430.tbcn.telia.com) |
| 22:15:03 | <mauke> | (because closures) |
| 22:15:40 | <monochrom> | There is reading the source material and actually accept it. Then there is reading the source material but misinterpret it to fit your echo chamber. |
| 22:15:49 | <Inst> | ^^^ |
| 22:16:19 | <Inst> | Part of the big deal of Haskell is that its concept of programming is extremely abstract and very divorced from the actual reality of the hardware. |
| 22:16:47 | <EvanR> | wait that's also C |
| 22:16:54 | <EvanR> | but people think it's portable assembly language |
| 22:16:54 | <mauke> | yeah, I was about to say |
| 22:17:03 | <Inst> | foothill vs everest? |
| 22:17:40 | <monochrom> | https://queue.acm.org/detail.cfm?id=3212479 |
| 22:18:03 | <monochrom> | ("C Is Not a Low-level Language" "Your computer is not a fast PDP-11") |
| 22:18:25 | <jumper> | mauke: you can do it in assembler though, although cumbersome |
| 22:18:37 | <Inst> | Yet, somehow, through work by both the compiler team and work by Haskell programmers, some, and I emphasize some, algorithms in Haskell can achieve 70-80% C. |
| 22:19:04 | <mauke> | jumper: assembler can't do functions at all |
| 22:19:10 | <jumper> | yes it can |
| 22:19:27 | <mauke> | this is a map-vs-territory thing |
| 22:19:39 | <EvanR> | or 110% C, relativity be damned |
| 22:19:39 | <mauke> | assembler doesn't have expressions |
| 22:19:42 | <jumper> | mauke: how do we define a function here? |
| 22:19:48 | <Inst> | You're thinking very low-level, my opinion is to let you try this on your own, with some help if you need it, until you either get through the report and have a partial understanding, or you give up and try easier resources. |
| 22:20:01 | <Inst> | Either way, to make the most use of learning Haskell, you need to learn a functional paradigm of thinking. |
| 22:20:05 | monochrom | ruins the conversation with "what about atlases and charts? domains and realms?" >:) |
| 22:20:41 | <mauke> | jumper: something that looks vaguely like f(x) from math |
| 22:21:20 | <jumper> | mauke: so you want syntax sugar? Macros then |
| 22:21:22 | <mauke> | you can emulate it in asm using the "subroutine" design pattern |
| 22:21:39 | <monochrom> | hahahahah |
| 22:21:43 | <mauke> | but then you can emulate closures in C by manually combining function pointers and environments in a data structure |
| 22:22:13 | × | euleritian quits (~euleritia@dynamic-046-114-207-017.46.114.pool.telefonica.de) (Read error: Connection reset by peer) |
| 22:22:20 | <mauke> | it's not something the language provides directly |
| 22:22:31 | → | euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) |
| 22:22:44 | <jumper> | mauke: ofc not, it's assembler, but you have total freedom to construct anything you can think of |
| 22:22:51 | <monochrom> | I once played with a certain function from libffi that helps with emulating currying and closures etc in C. :) |
| 22:23:26 | <monochrom> | It was more tedious than just calling Haskell. :) |
| 22:23:29 | <mauke> | monochrom: I wrote a toy version for x86 :-) |
| 22:24:08 | <mauke> | yay for memcpy'ing runtime generated machine code |
| 22:24:25 | <monochrom> | Uh that's hardcore :) |
| 22:25:17 | <mauke> | I think I got something like eprintf = bind(fprintf, 4, stderr); eprintf("hello\n"); to work |
| 22:25:27 | <mauke> | with a lot more type casts |
| 22:25:44 | <Inst> | BTW, I'm not wrong if I say that Haskell has a 5-stage compiler? |
| 22:26:17 | <mauke> | how are we counting stages? intermediate languages/representations? |
| 22:26:21 | <Inst> | yeah |
| 22:26:23 | <monochrom> | I don't know. Where do I find this 5-stage compiler? |
| 22:26:32 | <Inst> | Well, GHC to be more specific? |
| 22:26:43 | <monochrom> | And which are the 5 stages? |
| 22:27:00 | <dostoyevsky2> | Inst: Don't gcc/llvm usually only use 3 stages? I wonder what the other stages are about |
| 22:27:05 | <Inst> | Haskell -> Haskell Core -> STG -> Cmm -> Machine Code? |
| 22:27:08 | <ghoulguy> | denial, anger, bargaining, depression, and acceptance |
| 22:27:19 | <monochrom> | That's 4 ->'s. |
| 22:27:30 | <Inst> | 4 stage, then? |
| 22:27:34 | <monochrom> | Then yes. |
| 22:27:52 | <mauke> | CPP -> ... -> asm -> machine code |
| 22:27:55 | × | srk quits (~sorki@user/srk) (Ping timeout: 258 seconds) |
| 22:28:02 | → | Sgeo joins (~Sgeo@user/sgeo) |
| 22:28:26 | <monochrom> | I'm not doubting you. Along the same line, if someone asks "is it true that vector spaces have 7 axioms?", I will also ask them to list their axioms. |
| 22:28:43 | <Inst> | Because you prize rigor in thought? |
| 22:28:51 | <monochrom> | Because different people cut and count these things in different ways. |
| 22:28:59 | <Inst> | Ah. :) |
| 22:29:09 | <mauke> | is it true that there are 5 continents? |
| 22:29:23 | <dostoyevsky2> | Inst: I guess you have to write HPP as the 5th stage |
| 22:29:44 | <ghoulguy> | https://www.scs.stanford.edu/11au-cs240h/notes/ghc.html if you want to see more of the stages |
| 22:31:10 | <dostoyevsky2> | mauke: what are your top 7 continents in no particular order? |
| 22:31:10 | × | euleritian quits (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) (Read error: Connection reset by peer) |
| 22:31:48 | <monochrom> | :) |
| 22:31:48 | → | srk joins (~sorki@user/srk) |
| 22:32:01 | → | euleritian joins (~euleritia@ip4d16fc38.dynamic.kabel-deutschland.de) |
| 22:32:06 | <Inst> | mauke: 5 continents would go, greenland, antarctica, americas, afro-eurasia, australia? |
| 22:32:17 | <monochrom> | Clearly, Greenland should be one of the continents. >:) |
| 22:32:36 | <c_wraith> | and pluto should be a planet. :P |
| 22:32:43 | <monochrom> | And Tasmania. |
| 22:33:55 | <EvanR> | any number of additional stages induced by template haskell |
| 22:34:07 | → | bitdex joins (~bitdex@gateway/tor-sasl/bitdex) |
| 22:35:52 | <c_wraith> | Is TH limited to one "stage" per splice? |
| 22:36:27 | <mauke> | dostoyevsky2: pangea, polygondwanaland, mu |
| 22:37:18 | → | nate2 joins (~nate@c-98-45-169-16.hsd1.ca.comcast.net) |
| 22:42:01 | × | nate2 quits (~nate@c-98-45-169-16.hsd1.ca.comcast.net) (Ping timeout: 255 seconds) |
| 22:47:22 | × | [_] quits (~itchyjunk@user/itchyjunk/x-7353470) (Ping timeout: 252 seconds) |
| 22:48:18 | → | [itchyjunk] joins (~itchyjunk@user/itchyjunk/x-7353470) |
| 23:02:14 | × | srk quits (~sorki@user/srk) (Ping timeout: 272 seconds) |
| 23:12:48 | × | Tuplanolla quits (~Tuplanoll@91-159-68-236.elisa-laajakaista.fi) (Quit: Leaving.) |
| 23:13:07 | → | srk joins (~sorki@user/srk) |
| 23:35:46 | × | misterfish quits (~misterfis@84-53-85-146.bbserv.nl) (Ping timeout: 258 seconds) |
| 23:37:13 | × | zenstoic quits (uid461840@id-461840.hampstead.irccloud.com) (Quit: Connection closed for inactivity) |
| 23:41:56 | × | Friendship quits (~Friendshi@user/Friendship) (Quit: Leaving) |
| 23:42:18 | × | masterbuilder quits (~masterbui@user/masterbuilder) (Read error: Connection reset by peer) |
| 23:42:53 | × | jumper quits (~jumper@mobile-access-6df060-87.dhcp.inet.fi) (Quit: leaving) |
| 23:53:11 | → | Friendship joins (~Friendshi@user/Friendship) |
| 23:58:03 | × | tcard quits (~tcard@2400:4051:5801:7500:cf17:befc:ff82:5303) (Remote host closed the connection) |
| 23:58:21 | → | tcard joins (~tcard@2400:4051:5801:7500:cf17:befc:ff82:5303) |
All times are in UTC on 2023-10-16.