7 ms·
Why do our programs need to read input and write output?
- Etheryte 9y agoPerhaps I simply didn't understand the argument, but doesn't this simply move reading and writing to a different abstraction? Perhaps someone can reword the author's point, I feel like I'm missing something here.
- qbrass 9y agoHe just described batch processing like it was a new thing.
- tome 9y agoWhat part of the article makes you think the author believes he's describing something new?
- qbrass 9y agoThe lack of any acknowledgement that it had been done before. If you were trying to convince someone your concept is possible, wouldn't you point to an already existing example of it if you could?
- millstone 9y agoSay the user clicks somewhere in my program’s window. How does my program discover the location of the click without reading some input?
- tree_of_item 9y agoAs one example, the program might be written in model-view-controller style: * Your "model" is a type `Model`. * Your "view" is a function of type `Model -> Display`. * Your "controller" is a function of type `(Model * Event) -> Model`. So you don't need to perform IO to get the mouse click, since your program definition was already setup to handle incoming events. The runtime is responsible for feeding your controller events to get a new model, then running your view on the new model to create a display, then actually rendering that display.
- Gabriel439 9y agoTo clarify: the idea is that both the view and controller are built into the interpreter. The interpreted program builds the model and is written in a a purely functional and effect-free language
- JetSpiegel 9y agoIsn't that just pushing the side-effects to the runtime? What does it achieve?
- tree_of_item 9y agoIt achieves the goal of making your code side-effect free. The explicit goal of these sorts of projects is to push the side-effects to the very edge of the stack.
- maxxxxx 9y agoI don't understand the article. It's still input and output but in a more convoluted way and therefore better? Reminds me a little of articles you see from time to time like "if-less programming".
- Gabriel439 9y agoAuthor here: this is written for a primarily functional audience who already take for granted that it's good to minimize effects, but let me try to rephrase it another way for people who don't have that background Typically there are two ways that our programs can ingest values: * statically, via imports * dynamically, via reading values Why not ingest all values via imported code? If the import system is sufficiently lightweight this is simpler and easier than reading values the traditional way, plus you can read in things that are not plain values (like functions and types) In that sense, reading/downloading text and parsing it becomes an implementation detail of the compiler and from the programmer's point of view what you're left with is a network of pure functions that can refer to each other across impure boundaries
- 1_2__4 9y agoYou seem to be just playing with semantics and claiming it offers a new way of thinking about I/O.
- tree_of_item 9y ago"Playing with semantics" is a good description of programming language theory.
- Gabriel439 9y agoI don't want to think about I/O. That's the point I want to focus on connecting pure code together without thinking about the details of how that happens. I want this for the same reason that I don't want to think about manually allocating registers, managing memory, or caring about evaluation order Also, like I mentioned, traditional I/O can't import functions or types, so this is strictly more powerful
- tosstossy 9y agoI want my five minutes back.
- hexmiles 9y agoLike others i do not understand this article. It seem to propose an abstraction where we separate the I/O part from the "elaboration" part of a programs, so that our programs are entirely pure. But i don't understand why the import system and why only the compiler can read and write? Why can't we have the same benefits by using multi-threading/process? we can have "pure" thread and "i/o" thread that communicate with message passing? i feel like I'm missing something from the article.
- Gabriel439 9y agoThere are two separate questions here: * "Why should we limit I/O to the compiler"? Think of the compiler or interpreter as a small trusted kernel. It's a mostly fixed code base that you can inspect and audit. The programs that it compiles or interpret on another hand don't have to be trusted because they are perfectly sandboxed. They are effect-free purely functional code * "Why not use multi-threading for communication?" This is (in my eyes) the real problem that I'm trying to solve. Using effects as a message bus for composing code seems incredibly awkward and primitive, like explicitly managing stack registers.
- tree_of_item 9y agoExcellent, I've actually been working on something similar and I'm glad to see it validated. As I expected though, most people in this thread don't get it, which is understandable since it's pretty out there compared to the mainstream. I think they will once larger, "real" programs are written. I don't think I'm gonna be able to "reword" this for people here so it suddenly clicks, you're probably just going to need to see it in action to understand it.
- maxxxxx 9y agoWhy don't you describe a "real" program that uses this approach so we can see the benefit?
- tree_of_item 9y agoYep, that's exactly what I should do. My stuff is not ready to show off yet but I'll be happy to make an HN post once it's ready. In the meantime, Dhall is much further ahead, so you could check out more of Gabriel's stuff if you need more convincing.
- Risord 9y agoGiving ~precise and practical example can be suprisingly hard when you are working with some very different kind of thinking for a long time. At the end idea should be used in real world of course but it can take a lot of time to recreate lot of solutions which are resolved in mainstream but "reopened" in your world. I think this article is quite clearly just reprsenting idea for people working with functional side and maybe thinking something similiar already. So if you "cannot get it" and author cannot give ~easy answer don't judge yourself or the idea/author too much but accept that idea can be still very early phase and work-in-progress.
- maxxxxx 9y agoI just don't understand what's funktional or novel about this. That's why I asked for an example that could illustrate it. The good thing is that the author has no obligation to listen to me so let's see where this ends up.
- dahart 9y agoWhat's the appeal of taking pure functional all the way to an executable tautology? Inputs can be passed around in a pure FP world without reducing purity, so why remove them? We never got around to output at all. Assuming the compiler can't write the output file before the program runs, how would you see the result of any program run in this world? What about UI or network input? I'm imagining that if only the compiler were allowed to do I/O, I'd have to rebuild Chrome whenever I wanted to see a new site, or even see an update to a site, or change my preferences. Wait, scratch that, I can't change preferences, because it can't save. Is the shell allowed to do I/O? What about output to the monitor, does that count? It's not a file, but it's Turing equivalent to an output file.
- tree_of_item 9y agoChrome already ships a compiler today. Why wouldn't it continue to do so in your hypothetical?
- dahart 9y agoAre you referring to the JavaScript compiler? I don't understand your point, would you elaborate? The article is about factoring out all inputs from a program. Chrome's compiler is used to compile new inputs on the fly, it's reason for existence doesn't seem to mesh with the author's goal. FWIW, I'm trying to imagine the author's hypothetical. If you think I'm imagining something other than what he proposed, I'm all ears!
- tree_of_item 9y ago> I'm imagining that if only the compiler were allowed to do I/O, I'd have to rebuild Chrome whenever I wanted to see a new site, or even see an update to a site, or change my preferences. Wait, scratch that, I can't change preferences, because it can't save. Chrome IS the compiler. Your preferences are a program provided as input. Websites are programs provided as input. You wouldn't need to rebuild Chrome to change things.
- 9y ago
- mcnamaratw 9y agoMy favorite part is that injecting an attacker's code would not cause a security problem, because the platform is immune to side effects.
- marcosdumay 9y agoThe compiler is perfectly able to create side-effects.
- Gabriel439 9y agoHowever, the compiler/interpreter places an upper bound on the amount of code that we need to audit because it acts like a trusted kernel. We only need to audit the compiler/interpreter itself for safety and once we do so we can automatically trust all programs written in the language that it compiles/interprets
- marcosdumay 9y agoIn a general case, the compiler acts as a sandbox. How much harm the malicious code can do depends on the specifics of how much IO it enables. On the case of Dhall it's entirely safe, if you generalize it into a full OS equivalent system, you'd have to audit everything.
- mcnamaratw 9y agoI'm not making the claim. It seems to be in the linked article: ""That's a security vulnerability!", you protest. "You are ... literally ... injecting remote code into your program." Playing the devil's advocate, I ask you what is wrong with remote code injection "Well, for starters, if the URL is compromised the attacker can run arbitrary code like ..." ... reading and writing files? Dhall is totally pure and doesn't support any effects at all (besides heating up CPUs ). This brings us full circle back to our original "
- marcosdumay 9y agoOh, ok. On the specific case of Dhall, it can not.
- rocqua 9y agoSo, I am missing how this would work. Let me pick 2 examples. The first is about networking. How would I build, say, an http server in this thing? From the rest of this thread, it seems like you would advocate essentially a separate compiler for networking, and to 'read' from a socket, you just import. That seems like you are moving a lot of complexity to the world of compilers. Moreover, I don't see any way to then 'write' to that socket. Does the compiler essentially take a return value of main and then say 'well, guess this is what I want to send back'. That would suggest you can't do something like 'recieve handshake' 'send handshake' 'receive request' 'respond to request'. It seems to block interspersing input with output. My second example is a gui. It feels to me like your program couldn't in any way define the interface layout. All it could do is 'receive' and 'issue' events. It would take a specialized compiler, and a whole separate mark-up language to actually define the interface. How do you change the interface in response to input? I love pure code, and see the value in pushing the boundary of pure code as close to the edges as possible. However, code still needs side-effects to be useful, and I'd like to specify those side-effects in the same language as I specify my pure code. I'd like to decide for myself how far out to push the boundary of purity.
- Gabriel439 9y agoYes, this entails moving more logic into compilers/interpreters. For example, Dhall is actually designed this way: not only is it a command line interpreter but it's also a Haskell library that you can use to interpret Dhall expressions and marshal them into Haskell programs. So the Haskell language combined with the Dhall library becomes an "interpreter builder": a way to crank out a large number of specialized applications that are customized via an effect-free programmable configuration language For the specific example of a server, there would be two layers: * in Haskell you would implement a server configured by a Dhall expression (i.e. a hybrid server/interpreter) * end users program in Dhall, not Haskell * end users provide a record of pure functions (one for each API endpoint) that translate user input to output However, I think that's still just a superficial answer to the question. The next level is to ask: why do we even need a server? A server is just a way to distribute values, but Dhall already has a way to distribute values (and code): we just import them by reference. So why not just use that directly instead of standing up a server to reimplement what the Dhall interpreter already does internally You can encode markup in a purely functional languages. That's actually the easy part since you can treat it as an ordinary data structure. Actually, the harder part is coming up with a user-friendly way to transform a stream of events into a stream of outputs within a purely functional language. In my opinion, there is no clear consensus on the "right" way to do this, but the field of functional reactive programming is based on searching for clean solutions to this problem However, again, you need to step back and ask: what did we need this GUI for? In some cases, the GUI is the requirement (like in a game) so there's not much you can do to simplify things. However, in other cases -the GUI is just a poor man's interface to composing values and code, in which case we might just be able to replace it with importing URLs and paths using Dhall's built-in mechanisms (and perhaps replace all these bespoke GUIs with a general purpose GUI for manipulating Dhall expressions)
- robgibbons 9y agoHow would this IO model affect, say, Unix piping on the command line?
- dredmorbius 9y agoDismissing inputs for the moment: if you cannot write or transmit outputs, how does your program actually perform anything. If your answer is "side effects", you've merely redefined the term "outputs". As I see it, you'd have to have a program which was supplied its input, by the compiler, was evaluated by the compilier, and had its output imputed, by the compiler. You've only shifted the problem of input and output sanitisation elsewhere.
- Gabriel439 9y agoThe way I would phrase it is that you've concentrated your input and output sanitisation in a trusted kernel (i.e. the compiler/interpreter) and that puts an upper bound on the amount of code that you need to audit (just the compiler/interpreter code base). That's more realistic than auditing all programs written within the compiled/interpreted language