These are chat archives for got-lambda/expression

28th
Oct 2018
jensli
@jensli
Oct 28 2018 09:27
@jolod @Jell Interesting with well though-out principal arguments against static typing, I will watch Rich's presentation.
Magnus Therning
@magthe
Oct 28 2018 09:46
@jolod I don't understand his argument at all.
Magnus Therning
@magthe
Oct 28 2018 10:10
To me it sounds like he's suggesting that when writing business systems in languages with static type systems Maybe will be everywhere in the types. Even for data that is required. That would be such a silly strawman argument that it borders on trolling, which makes me suspect I don't understand it at all.
Pierre Krafft
@Zalastax
Oct 28 2018 10:15
@Jell please expand on your issues with gradual types. Gradual types lets you be completely static if you want so it's up to you if you want to allow dynamic parts/type assertions in your code base.
@Jell Both TypeScript and PureScript are backend languages ;)
Magnus Therning
@magthe
Oct 28 2018 10:18
@Zalastax did you see the announcement of Pure-C?
Pierre Krafft
@Zalastax
Oct 28 2018 10:20
@magthe no. Link?
Pierre Krafft
@Zalastax
Oct 28 2018 10:25
Neat!
Do you use npm dependencies in PureScript? Missing out on all the libraries there could be a big drawback, no?
Jean-Louis Giordano
@Jell
Oct 28 2018 10:33
@Zalastax I mean when mixing dynamic and static using gradual typing. If you’re fully static then you get the benefits of static, but if you are partially dynamic unless you add runtime boundary checks between typed and untyped you might get runtime type errors in your statically checked code (making it it unsound if I use the words correctly)
@Zalastax I did not consider PureScript & TypeScript running on NodeJS, so I guess that’s an option.
(for backend dev I mean)
Pierre Krafft
@Zalastax
Oct 28 2018 10:48
In the academic papers on gradual typing the compiler is supposed to add runtime checks when going from dynamic to static, but that's not used in practice so I digress. Nevertheless I don't find it a problem that you might get a crash in the statically checked part - it's about the same level of annoyance as getting the crash in the dynamic part (the process/current task will fail and I need to pull out the debugger).
Of course it's a lot better to get the crash where the problem originates. I learned that lesson when I gad to debug Erlang code that did not follow the let it crash principle - it was hell.
Jean-Louis Giordano
@Jell
Oct 28 2018 10:55
yeah I think it’s an active area of research in the racket community to add boundary checks to static code? my understanding was that the overhead was problematic
and yeah I’m not saying it’s more annoying to debug i the static part than in the dynamic, it’s basically the same, which is kinda my point. But I guess like vaccines you have some form of herd immunity once you have enough statically checked codebase
Jean-Louis Giordano
@Jell
Oct 28 2018 11:01
if you have 10% static, it’s probably not worth it as you add overhead but still get the same errors, but perhaps at 90% static the pocket of dynamic code might be small enough to facilitate debugging?
well obviously not saying that dynamic is the answer there anyway because you need to add runtime overhead anywhere you want some kind of boundary checks (to let it crash), so I’m not sure what’s why point anyway :p
Jean-Louis Giordano
@Jell
Oct 28 2018 11:11
for reference, my gradual typing experience was with core.typed in clojure which I thought was really cool (and can do cool stuff like the typed racket occurrence typing), I haven’t tried typescript
Pierre Krafft
@Zalastax
Oct 28 2018 12:56
Is occurrence typing an instance of flow-sensitive typing? I agree that it's super useful!
jolod
@jolod
Oct 28 2018 14:39
@Zalastax There was a reddit thread on PS on the backend, but IIRC Phil Freeman said there was no goal of replacing Haskell, and that the browser was the real target for PS. That was a few years ago though.
Phil Freeman has been pretty clear on that there have been trade offs when targeting JS, and a big one is laziness.
Don't know what the current thinking is though.
For instance there seems to be no interest to rewrite the compiler in PS instead of Haskell.
jolod
@jolod
Oct 28 2018 14:45
@Zalastax PS uses npm, but that's not a problem. All JS dependent code is accesses through foreign import ....
@Zalastax And foreign import maps to a file of the same name, but ending in .js instead of .purs. I guess you would use another but similar system if you compile to C.
jolod
@jolod
Oct 28 2018 14:50
@magthe I think he wants to program Clojure in Haskell and finds that Haskell is a poor language for programming Clojure.
Magnus Therning
@magthe
Oct 28 2018 15:11
@jolod But I doubt he even programs Clojure like that, I mean just take his statement and replace "maybe" with "nil-checks" and you have a statement that's true for Clojure.
Magnus Therning
@magthe
Oct 28 2018 15:19
But no one writes Clojure like that. One adds a validation layer to create an inner part where one can rely on the data and skip nil-checks.
The nil-checks that are left in the inner part are on values that are optional to the business logic. And as he himself says, not all things are optional in the business logic.
jolod
@jolod
Oct 28 2018 18:32
@magthe I think a key to understanding what he is saying is the following sentences. He says, at https://youtu.be/2V1FtfBDsLU?t=3010, "Nothing is of type maybe something. If your SSN is a string, it's a string. You either know it or you don't. Jamming those two things together makes no sense. It's not the type of the thing. It may be part of your front door protocol, that you may need it or not, but it's not the type of the thing."
The why I understand this, is that he does not like to have types like newtype Person = Person { name :: String, ssn :: Maybe SSN, ... }.
Because a person doesn't have a "Maybe SSN". You might have the SSN present, or it might not be there, but a person has an SSN, not a Maybe SSN.
This I think points to how he thinks about "information systems". He, a minute or so earlier, says that if you have a piece of info here, and another piece of info there, and need both of them you just merge them together.
jolod
@jolod
Oct 28 2018 18:40
Let's say you have two records, one holding x and maybe y. And another one holding y and z. What is your result type?
If you merge them.
Pierre Krafft
@Zalastax
Oct 28 2018 18:41
So the problem is constructors then? In Erlang the type would be specified as string() | undefined
jolod
@jolod
Oct 28 2018 18:42
As he puts it, you have an algebra for information (if you store it in maps). You can merge, take subsets, etc.
So I don't think that the problem is a single feature or a single "thing".
It's like trying to explain to non-FP programmers how the experience of programming functionally is. You show them "map", and they say "so the problem is C-style for loops then"?
Pierre Krafft
@Zalastax
Oct 28 2018 18:46
But he does know that some languages let you do set algebra with types? I really don't get his position
jolod
@jolod
Oct 28 2018 18:47
Does he?
I get his position. That doesn't mean that I totally agree with it though.
Magnus Therning
@magthe
Oct 28 2018 18:48
@jolod but I still think he's making no sense, I fully understand that the SSN is a string, and you either know it or you don't. I just think that he's confusing when he says "you either know it or you don't", how do you know that you don't know? In a typed language you have to explicitly say Nothing, in his language of choice you inspect the map and get a nil, I see very little difference between these two things.
That's why I don't get his position, the not-knowing has to be represented somehow, he prefers implicit, others prefer explicit.
jolod
@jolod
Oct 28 2018 18:50
That was my first thought as well. But then I thought about it some more and put it in context, and that changed my interpretation.
I think it is an error to reduce it to "he prefers implicit, other prefer explicit".
He specifically argues that information constructs should be open, for instance.
I would not be surprised if he did not know about row polymorphism, since it's not exactly a mainstream feature (and that he spends some times ranting on positional arguments).
He also only mentions C++ and Java when he talks about type parameters.
So I think that in his mind, when he says "parameterize an informatin system", and you want that system to be as open as you can be if you do not have open constructs such as with rows, you would have to have "maybe everything".
So you would have a Person type/class that has maybe all the info you might possible want to access for a person.
Magnus Therning
@magthe
Oct 28 2018 18:55
Yes, or you say "run-time check everything".
jolod
@jolod
Oct 28 2018 18:55
You're missing the point, I believe.
It's not about when you check it.
Magnus Therning
@magthe
Oct 28 2018 18:58
Very possible, because I don't see any point... it sounds like he's talking about Maybe, as in Maybe String for an SSN, contra "maybe the SSN is there, maybe it isn't"... but perhaps I don't understand it at all.
jolod
@jolod
Oct 28 2018 18:58
So if you have a function that needs the SSN, you write a function that requires that. If you have a function that requires civil status, when you have a function that requires that. If you want to have a type that you can use at both places, and that might not be populated in all parts of the system, then you would have to have that the person type has maybe an SSN and maybe a civil status.
Magnus Therning
@magthe
Oct 28 2018 19:01
Indeed, but only if your business logic and context allows that, and in Clojure I'd have to add logic to check for the presence!
jolod
@jolod
Oct 28 2018 19:02
Imagine that you have some tax forms. Under different circumstances you have to fill out different fields. Potentially all fields are maybe. But usually it is the case that if one field is filled in, a whole bunch of them are (or should be) filled in.
The problem here is that in order to get rid of the Maybes that you now know are there, after checking one field, you have to change the type.
If you encode all the different combinations for this imagined tax form (or any other non-trivial form), you end up with a fairly large data type with a lot of different but very similar constructors.
Magnus Therning
@magthe
Oct 28 2018 19:05
Yes, and in Clojure I'd have to add a lot of consistency checking. To me it sounds like he's saying there's a free lunch... and I don't think there is.
jolod
@jolod
Oct 28 2018 19:06
You're arguing pros and cons. If you don't understand his point then it's hard to argue either pros or cons.
Pierre Krafft
@Zalastax
Oct 28 2018 19:06
The answer is more types! With dependent types you can have a datastructure with a bunch of maybes and pair it up with a proof that certain fields are actually not Nothing. Only half joking
jolod
@jolod
Oct 28 2018 19:06
@Zalastax You get his point though?
Magnus Therning
@magthe
Oct 28 2018 19:07
No, I'm saying there are pros and cons, my take on his talk is that there are (almost) only cons with strict typing.
jolod
@jolod
Oct 28 2018 19:07
He says it's an anti pattern, yes. :-)
Well, you keep bringing up how you would do it in Clojure, which I don't think is relevant since we're talking about how you/I intepret Rich Hickey's stance on static types for information systems.
Or not the stance, that is clear. But his motivations.
Magnus Therning
@magthe
Oct 28 2018 19:09
You can s/Clojure/dynamic-typing if you want to
But I think Clojure, more than any other language I've seen, encourages the make-a-large-map-and-pass-it-to-everything style of writing functions, which I understand is Rich Hickey's "good pattern"
jolod
@jolod
Oct 28 2018 19:11
But that's again jumping the gun. It could be that both are bad. But nothing is gained by redirecting the discussion to "the other side". There's value in just focusing on how a statically typed information system looks and works. And specifically right now how it would work to do the things that Rich Hickey wants to do and understand his reasons for arguing the way he does.
Me, personally, I think that "you have to go an update every place where you pattern match if you add another constructor" I a good thing. I hear that being argued as a negative and bad for maintenance. But for me it means that I actually check that my assumptions are correct, and if that keeps happening all the time I might have to think about my data model and the abstractions I'm using.
But I do understand the argument. I just don't agree with it for the programs that I write.
Regarding free lunch. I don't think that is what he's saying. He is saying that static types misdirects focus to the problems that he finds trivial, away from the problems that he find important. See the slide at https://youtu.be/2V1FtfBDsLU?t=1718 .
jolod
@jolod
Oct 28 2018 19:16
Typos and inconsistencies (e.g. assuming you have a value when you have nil) is the lowest order of magnitude for me.
err, for him.
Personally I really don't like nils. :-)
I would be much happier if Clojure by default threw an exception on (:foo {}).
It's so easy to get the nil default behavior: (get m :foo nil). And now I'm explicit about the value being optional.
Going in the other direction is not as easy. Destructuring defaults to nils, and you can make typos eg (defn foo [{:keys [this that] :or {:this 3 :thet 7}}] ...). (Not 100 % on the syntax, I never use it.)
jolod
@jolod
Oct 28 2018 19:23
I understand the reason it is the way it is. Doing the opposite would make some things that are very easy now rather cumbersome, but for me it's the wrong trade off. But given Rich Hickey sees this as the least of worries, it makes sense that Clojure is what it is.
Pierre Krafft
@Zalastax
Oct 28 2018 19:24
@jolod no I don't actually get his point. I hear the words but I don't get what he actually means. Especially when in my mind there are a solutions to every thing I can conceive he means
jolod
@jolod
Oct 28 2018 19:24
@Zalastax Are those solutions in his mind though?
Let me rephrase that. It was ambiguous. Is he aware of those solutions that you are aware of.
Pierre Krafft
@Zalastax
Oct 28 2018 19:25
Perhaps not but to know that I'd have to email/meet him
jolod
@jolod
Oct 28 2018 19:26
So you have two main candidates: either he knows but doesn't make any sense, or he doesn't know and makes sense. Which would you bet on?
(Given that you agree that assuming that there exists different sets of knowledge in which it can make sense, and that those sets are not unlikely.)
Pierre Krafft
@Zalastax
Oct 28 2018 19:28
I'd bet on him not knowing or that I am missing some experience that would make the solutions I have in mind not good enough
jolod
@jolod
Oct 28 2018 19:30
So does he make more sense if you assume that he does not know of the solutions that you can conceive?
Pierre Krafft
@Zalastax
Oct 28 2018 19:31
Sort of, but mostly because then I can dismiss everything he says as angry yelling at Java
jolod
@jolod
Oct 28 2018 19:31
And that I think is at least 50% correct. :-)
Magnus Therning
@magthe
Oct 28 2018 19:32
How is it "jumping the gun"? He's saying one is an anti-pattern, and saying very little, if anything, bad about the other.
jolod
@jolod
Oct 28 2018 19:33
@magthe Because, at least in my mind, the topic was "He doesn't make sense and I don't get his point", not "his point is invalid and he's wrong in his conclusion".
Pierre Krafft
@Zalastax
Oct 28 2018 19:34
I think e's unfairly dismissing types as mostly hlping with typos but I'm preaching to the choir already
jolod
@jolod
Oct 28 2018 19:34
@magthe I'm not arguing with you that Rich Hickey is correct, or that static types are an anti pattern.
Magnus Therning
@magthe
Oct 28 2018 19:35
I was trying to say "he doesn't make any sense or I don't get his point"... he's not making sense in that he aggressively puts one down, and says very little bad about the other.
I know that @jolod
jolod
@jolod
Oct 28 2018 19:35
The starting point was this thing about "maybe everything". That doesn't really have to do with saying one is better or worse.
And I argue that he is not simply a case of "when you check" or any of the other things we discussed, but that it's a part of a different perspective.
Magnus Therning
@magthe
Oct 28 2018 19:38
Oh, based on how he said that, and the mocking phrase of "no one has a Maybe SSN" I'd say it most definately was the case that he was trying to get across one being better and one being worse.
jolod
@jolod
Oct 28 2018 19:39
While I think that he thinks that one is definitely better than the other, I don't think that that has to be involved when discussion the more philosophical question on how to read the type arguments.
Magnus Therning
@magthe
Oct 28 2018 19:40
Anyway, I don't think I've ever heard Rich Hickey say anything I completely agree with when it comes to types :grin:
Pierre Krafft
@Zalastax
Oct 28 2018 19:40
I find it ridiculous to have a language where you can't opt out of null :sob:
Magnus Therning
@magthe
Oct 28 2018 19:42

@jolod by "philosophical question on how to read the type arguments", do you mean

So if you have a function that needs the SSN, you write a function that requires that. If you have a function that requires civil status, when you have a function that requires that. If you want to have a type that you can use at both places, and that might not be populated in all parts of the system, then you would have to have that the person type has maybe an SSN and maybe a civil status.

?

jolod
@jolod
Oct 28 2018 19:43
Yeah.
And now you say "But that's not how we use types in Haskell", perhaps?
:_)
Magnus Therning
@magthe
Oct 28 2018 19:46
Haha, no, I just wanted to know what you referred to when you wrote "philosophical question on how to read the type arguments"
Because, to some extent I still think that bit only is half of what needs to be said. :)
jolod
@jolod
Oct 28 2018 19:49
So where I agree with Rich Hickey is that you end up shuffling around data between different constructors if you want to be precise about Maybeness.
I meant that for all languages actually used, @Zalastax ;-)
Magnus Therning
@magthe
Oct 28 2018 19:50
Oh yes, absolutely... you do that, though hopefully you an limit the majority of that to a validation step early in the processing of input.
jolod
@jolod
Oct 28 2018 19:51
So here's where it's important that he's talking about "information systems", I think.
He optimizes for programs where this is the bulk of the system.
Magnus Therning
@magthe
Oct 28 2018 19:53
Well, it would really help with a clear and crisp definition of "information system" then... AFAIK there is none.
jolod
@jolod
Oct 28 2018 19:54
This is why he says "if you would parameterize an information system", you'd get "maybe everything".
A large part of the talk is about that, indirectly. So the way I listen to is is that if he says "if you would parameterize an information system ..." and I'm like "uh, no, not in my experience", then I think "so are there any systems where this could be true? OK, let's assume that's what he is talking about (until that is contradicted by another statement)".
And there are many bits and pieces. He also adds the qualifier "situated".
IIRC that basically meant "does a lot of IO".
s/listen to is is/listen to it is/
jolod
@jolod
Oct 28 2018 20:04
On a related note, for me it was quite an important insight that Clojure is data language first, while Haskell is a functional language first.
This is exemplified in this old blog post: https://adambard.com/blog/refactoring-refactored/
The reason I say that is that if you have immutable data, you end up only needing functions (in the pure sense) to manipulate that data. Any side-effecting procedure would just produce heat. Conversely, if all you have are pure functions you can only work with immutable data. The result is similar, but the difference in emphasis between Haskell-likes and Clojure is quite striking I think.
jolod
@jolod
Oct 28 2018 20:11
So in the blog post above, you see how the main piece of the code is a reduction over map, holding three values. There is no reason for the computations to be coupled like that, other than that is the shape you want your data afterwards. It's telling that the first function in add-to-statement is assoc, i.e. there is no let binding to share any computation between the values in the map.
(Interestingly, there is a shared value, but it's not utilized.)
Magnus Therning
@magthe
Oct 28 2018 20:14
Yeah,so maybe all I've been doing is argue that all systems I've ever worked on aren't information systems :grinning:
jolod
@jolod
Oct 28 2018 20:16
EXACTLY! :-)
Magnus Therning
@magthe
Oct 28 2018 20:16
And I apparently lack the imagination to even understand what kind of system it is he's talking about.
jolod
@jolod
Oct 28 2018 20:17
Seriously though, we all agree that he's a bit narrow-minded when it comes to types.
Just when this came out, I did some stuff that was very much like the system he's talking about, so I totally got where he is coming from. Most of the time I don't have "everything maybe" in my data models, even at the edge (other than API or DB error).
But that was one time when I actually did. I have really Maybe everywhere.
A good exercise was also when I wrapped a JS library called cheerio in PureScript.
cheerio is very "flexible", and if you get many matches when selecting something and just treat it as a single value, you get the first value.
jolod
@jolod
Oct 28 2018 20:22
That of course rubbed me the wrong way. If I think I have just one value, I want to know that my selection really got exactly the value I was looking for. So of course I had an interface where I could turn a selection in a singleton value, and then only treat that value as a scalar.
It seems like the right things to do, but at the same time I'm not quite sure it was the right decision.
So selection to singleton gave maybe a value.
But yeah, most of the time it's like "it works, OK, good" and it would only be if something external changed that it would not work. But then I would probably get errors elsewhere also, so I might have been paranoid and spent time on something that wasn't really productive.
So I had maybes everywhere and I had to prove that I had just one value and not many values. Because asking for a value from a selection would of course also give me a maybe, since the selection might be empty, hence I encoded in the types the difference between maybe one or maybe many. Perhaps just maybe many was enough.
Magnus Therning
@magthe
Oct 28 2018 20:29
So, would you today have written it in a dynamic language, maybe Clojure, just to get rid of "Maybe everywhere"? And if so, how would that have changed the internal logic?
jolod
@jolod
Oct 28 2018 20:37
More than 50-50 for Clojure, I think.
But for my main spare-time project, for which I'm using PureScript, I started out with Clojure and I would absolutely not go back to Clojure.
That's the same project as the DoubleGraph code came from.
Magnus Therning
@magthe
Oct 28 2018 20:39
So for that one in particular... in what way would the logic change is you went for Clojure instead?
Like, less lifting into Maybe?
jolod
@jolod
Oct 28 2018 20:39
No, I just wasn't able to reason about the code because no types! :-D
Types help me see the bigger picture, and I found myself going down the wrong paths in Clojure.
And the funny thing is, it is still rather exploratory, and that's when types are supposed to be in the way. On the contrary, for this project.
Magnus Therning
@magthe
Oct 28 2018 20:41
I meant for the one where you did end up with "maybe everywhere" and would now have considered Clojure (not the main one).
jolod
@jolod
Oct 28 2018 20:44
I think that regarding Maybe, I would of course use nil checks instead of case on Nothing/Just. Obviously no fmapping, don't know how that would affect things. I do get tired of doing (when (argument) ...) so if that was everywhere I'd make a mapMaybe function. Problem is, it wouldn't work with multiple arguments (where you'd use Applicative), but if that was a problem I'd write a macro, and yes, it would be not so nice.
Most of the time it was like "if x and y are present, then produce a z otherwise nothing" which is perfect for <$> and <*>.
Magnus Therning
@magthe
Oct 28 2018 20:46
OK
jolod
@jolod
Oct 28 2018 20:46
But I don't know. As I said, it's more than 50-50, but it's not 90-10 to Clojure.
There are parts where Clojure shines, and the question is how large that that part would be. Hard to say without actually doing it or revisiting the code and look closely.
I can live without many of the abstractions in Clojure, but I do miss ADTs though.
Sometimes you options are just limited, and I don't want to forget to update all the places where it's needed if I were to add one or change the data.
I find that doing functional refactoring in Clojure is easy. "Data refactoring" is not pleasant at all.
Data refactoring in PureScript is super nice.
jolod
@jolod
Oct 28 2018 20:53
So in my main project I don't know which data model I want, and that's why I changed from Clojure. It's really not a "tax form" system.
jolod
@jolod
Oct 28 2018 20:59
What about you, would you choose Clojure over Java (and you'd have to write like old school Java, not new fancy Java 9 Java)? Or put a bit more fair, Clojure vs a non-functional language but with very good type system (don't ask me to give an example!).
Magnus Therning
@magthe
Oct 28 2018 22:06
You mean if I were writing a system where the datamodel was such that I couldn't really do validation at the edge?
I'm not sure what oldschool Java would buy me over Clojure, I think both would lead to permeating presence-checks.
jolod
@jolod
Oct 28 2018 22:07
I was thinking of any kind of program you typically write. :-)
Magnus Therning
@magthe
Oct 28 2018 22:07
If I had a language with good type system, that allowed me to lift functions similar to liftA<n> in Haskell, I'd be interested in trying out the permeating Maybe.
jolod
@jolod
Oct 28 2018 22:08
That's why I said non-functional. So lifting functions in the generic way that Haskell allows would not be OK. ;-)
Anyway, for me functionalness dominates over typiness.
Magnus Therning
@magthe
Oct 28 2018 22:09
Well, I dislike Java with a passion, so I'd be hard pressed to ever choose that.
jolod
@jolod
Oct 28 2018 22:10
(Numerical computation is a special case, in which the paradigm is much less important.)
Magnus Therning
@magthe
Oct 28 2018 22:11
Much of the code I write is bascially stream-processing, so I'd choose Clojure because it lends itself to that fairly well, threading macros and such. And if I want a bit more control I'd pull in something like funcool/cats.
Marco Zocca
@ocramz
Oct 28 2018 22:12
guys
200 messages in a day
o_0
Magnus Therning
@magthe
Oct 28 2018 22:13
@ocramz yes, you can safely skip everything! :lollipop:
Marco Zocca
@ocramz
Oct 28 2018 22:17
I did follow on and off but also got mostly lost. Though I'm being On Brand by reading about De Bruijn indexing
Magnus Therning
@magthe
Oct 28 2018 22:23
I think it was in that presentation, The Most Beautiful Program Ever Written, that De Bruijn indexing was described as "perfect for computers, impossible for humans" :)
Pierre Krafft
@Zalastax
Oct 28 2018 22:25
de Bruijn calls it a hack. Oh the things you do for theorem proving
jolod
@jolod
Oct 28 2018 22:27
@magthe Have you used funcool/cats for real?
Magnus Therning
@magthe
Oct 28 2018 23:48
@jolod only a little bit, I have written some code that's running in almost-production at work