Category Theory II 1.1: Declarative vs Imperative Approachyoutube.com
The way I understand functional/reactive programming is that it treats all input as it were pre-existing.
So, instead of thinking of:
okay, now the user moved the mouse or clicked or pressed a key and we have to react to it and have handlers for it and so on,
we think like this:
okay, here’s a list of all actions that the user will do, so it sort of says “I know everything about the universe, I know all the future”, this is the list of mouse clicks from now till the program terminates, this is the list of keys that the user will press, okay, here is a list of input from the network that will come, okay? Here, go and calculate something for me. And you just go and take this list and say: okay, I will apply a function to a list like `fmap`, or I can do a fold on this list, or I can merge two lists, stuff like this - you just work on the whole list as if it existed. Of course it doesn’t exist at the moment the program starts running but it doesn’t matter. It’s like, if you tell it ‘’do something for every digit of pi”, does it have every digit of pi? […] it doesn’t have everything at the same time. […] in a lazy language like Haskell we don’t care that we don’t have the whole list. Conceptually we do have the whole list. When time comes to get the next element, well maybe we’ll block / the system will block waiting for user input, but we don’t care: we just have a list and operate on the whole list […].
Bartosz Milewski, https://youtu.be/3XTQSx1A3x8?si=VXcQVdOJ6koJ16oa&t=1904
Don’t think about how things are implemented in hardware. What computers are is just one of the many models of computation. We shouldn’t get attached to it. You can perform computations in your mind, or with pen and paper. The physical substrate is irrelevant to the idea of programming.
Milewski, The Dao of Functional Programming, p. 1
[…] when we write code in what now I’m calling programming only language – okay, what we’ll call programming language, I’m now calling a programming-only language, meaning it can only talk about the surface and only talk about the implementation, so it misses the heart of the matter and the reusability. I think that the purpose of my code is to take some data and transform it into other data. That’s, of course, a functional perspective, but even when you’re doing imperative programming, you’re still doing that just in a sequential way. Start with some data, you end up with some data.
But I don’t think that’s really what computation is about. I think that’s what the surface layer is about. I think that’s what the executable is about. But the whole process of why am I generating this computation and why am I happy with it, or should I be happy with it, and if so, why, that is not about transforming. The purposeful computation, or meaningful computation, is not about transforming data into other data. It’s about transforming meaningful data into other meaningful data and doing it meaningfully. And what I mean by that is that when I write code to do, say, binary addition, there’s a reason for that code. It is not just because I have a vector of bits and a vector of bits. It’s because I have a particular interpretation of that vector of bits. I have a particular way in which I’m interpreting that vector of bits as a natural number. So my job in constructing computation is not to transform data to data. It’s to transform, in a way, an interpretation. So there’s a type of data, and there’s a type of its meaning, and then there’s a function from the formative ladder, from the representations to the meanings. That’s the domain. That’s what I’m transforming. That’s what I’m taking in, is meaningful data, is the data type interpreted in a particular way. And that’s what my computation is generating. That’s the whole thing. That’s the higher-dimensional thing that has the purposefulness in it and has the ability to then have the logical proof in it as well.
When I’m just reflecting, I look back, and when I’m programming, of course, I have an interpretation in mind. Everybody has an interpretation of mine, but what often happens is maybe I’m working with you and we have different interpretations in mind and our programming language cannot capture either one of those. And so it cannot notice the difference. You write your code. I write my code. They’re both correct. We put them together. It’s not correct. Why not? Because we didn’t say what we meant. We said, “I’m transferring bit vectors to bit vectors.
[…]
So our programs miss their purpose, and the languages cannot capture that purpose, and therefore they cannot support us in fulfilling it. Especially we, who like typed languages, for instance, appreciate that the program is helping us, supporting us in fulfilling our intentions.
https://haskell.foundation/podcast/62/ (0:52:06)
#17 The Lost Elegance of Computation - Conal Elliottopen.spotify.com
[…] there's a mental bottleneck which is the von Neumann paradigm. The von Neumann style in the in the title of this during award lecture is exactly this. And it forces to think small. We cannot think clearly and profoundly and deeply and gain insight within the von Neumann model of programming. The von Neumann programming is still the dominant model of programming. Operational semantics, which is mainly what PL people are taught is essentially mirrors this weakness. it's an essentially sequential and mechanistic way of thinking which is not rooted in beauty. It is sort of fundamentally sequential, whereas computation isn't. If if you think it is, it's because you've been programmed right with this deep misunderstanding.
[…]
So anyway, this turning a word lecture for me is really about breaking out of the Von Neumann bottleneck, the spiritual, mental, cognitive, right, philosophical bottleneck, and and and getting back into this programming.
https://open.spotify.com/episode/4jPTxGfaUa84IqsQceKywL (1:04:55)
There's one meta idea that applies, I think, to everything everybody should ever do. Certainly applies to everything I do, which is you should understand what you're talking about in the simplest, most elegant compositional terms. That is denotational semantics. That's what I call giving, having a denotation.
So all your types have a mathematical model. It's simple and of course it has to be precise. Otherwise simplicity is an illusion. OK, so it's as simple as it can possibly be. And then every operation that you provide can be fully explained in terms of that model and that model has nothing to do with the implementation at all.
OK, so so it it it it's a very severe discipline that forces you to to think in the clearest well, it encourages you to think in the clearest possible way about what you're trying to say, independent of any bias about implementation.
That's very hard for people who have been conditioned to think that programming is about making machines do stuff. Because any anything. You know, if you think computation and if you've been taught operational semantics and operational thinking, and like, like linear algebra is about arrays and machine learning is about neural Nets, all these like arbitrary bad choices about particular representation, or programming is about sequences of effects, all these harmful ways to look at things.
https://open.spotify.com/episode/4jPTxGfaUa84IqsQceKywL?context=spotify%3Ashow%3A1gE06aXNjm4BEcwbsow0Zu (1:56:43)
Yeah, so so I thought I got to think about 3D graphics in a a functional way, a compositional way. A way of what it means, not how it not what it does.
OK. And that's the difference. The graphic systems are almost always implemented the way almost everything else is implemented. But especially graphics it seems is is if they are a graphics program is a sequence of commands, maybe structured, you know sequence of commands, the words like you might have loops and subroutines, what they used to call them, right. So procedure definition, so on. But they're essentially just ways of of organizing sequences of instructions that have side effects, right? But instead of the system memory, they're going to be the video memory, right?
And the pattern that we want in memory after we're done as an emergent effect is one that looks like something to you like some geometry or something like that.
All right. But that model is a terrible model if what you care about is clarity. Because it's extremely hard to reason about in exactly the way John [Backus] has said that that because of imperative programs, that is programs that are about sequences of effects and which have no nice mathematical properties, therefore they cannot give you any powerful insights.
So what I did instead is: I said OK, what are graphics programs for? In other words, what are the meanings they are trying to convey? So I want to make a graphics program. It's because I want to help somebody look through a tool at something they are interested in. So I'm trying to invent a telescope for something. What is that something? And that's the important thing. And the secondary thing is how can I make a device that helps you look through it? How can I use a computer? How can I make a device you can look through to see what you want to see and then how can I make a language describe what you want to see?
That's very different from the dominant design paradigm, which is how can I make a language or a library so that you can describe a sequence of effects right, that emerge that have this, you know eventually, you know that cause a billion effects whose whose overall aggregate result is to draw a picture, right?
Because it because it messes up these two things. The essence of what it is that the the idea you're trying to describe and give somebody a a a opportunity to look at and then how the machine works and what are the kind of physics in a way what are the effects. So I divided those two things and instead of a language of rendering or even of affecting a data structure that would get rendered I designed a language with a library of vocabulary, typed, composable vocabulary of geometry and colors. I mean it's like essentially what Euclid did within a modern a more modern vocabulary, a more modern linguistic framework, right? So a collection of types and typed operations on three-dimensional things. […]
https://open.spotify.com/episode/4jPTxGfaUa84IqsQceKywL?si=168fed48e7fe47fd (1:32:19)
Denotational Design Principles
#21 Denotational Design - Conal Elliottopen.spotify.com
So in denotational design, you say for most important thing is, what do I want to talk about? Ok, I'm going to talk about these linear maps. And then the second question is, what is a language? What's a vocabulary in which I can express these things? I can build them up. I combine them, build them out of nothing, all these things; it's these operations. What algebraic abstraction already exists? And we've already proven things. We've already learned it for some other reason.
Then the next step is now we're going to say, OK, so then now I kind of understand the mathematical realm, the specification. That's the story I'm going to tell the user. Now what about the implementer? What I'm going to tell the implementer, which may be me, maybe somebody else. What I'm going to tell them is I want you to, I want you to find a way of implementing the first story. And there are two kinds of choices to make. One is the representation you're going to use for the things of interest. And the other is how you're going to implement the operations. Which operations? The one that the first model already wants to talk about.
Now, how do you know how to implement them correctly? Well, there's two questions. What does it mean to be correct? And then how do you get there? What it means to be correct is always the same. It's a homomorphism. OK, So what homomorphism you have to talk about? How does the representation mean the things we're talking about? if you don't know what the representation means, you can't possibly address the question of how to implement operations on them because it's only the meaning that guides them. You have to know what the up the arguments mean and what the operation means.
Philosophy of object-orientationforum.malleable.systems