I agree with you. A type amounts to the sum of operations that are valid on an object conforming to that type.
A file object is a very basic, general type, that allows open, read bytes, write bytes, close, maybe seek, maybe some ops are restricted (read-only, write-only) etc.
I don’t think it is generally appreciated how far it gets you to have a unifying simple interface. You can always add a complex one, you know?
It's interesting both of you had different answers. I realize that the streams interface was a Sys V thing but would the Unix's "everything is a file" generally be option (2) in the OPs comment then? I feel like I've heard the phrase so much and just always assumed it was (2.)
If Unix is "everything is a file", then Plan 9 is "everything is a network filesystem".
If you have a laptop and a desktop, and your desktop has a printer attached, can your laptop just print to it? In Linux, you have to set up CUPS, open network ports, download drivers, and generally set up both machines to be able to "talk printers". In Plan 9, your laptop just opens the desktop's printer file over the network, and prints.
Plan 9 provides a generic framework for writing server-client programs based on the 9p message-oriented protocol; nothing more nothing less! In Linux, there is no such widely generic equivalent. Every server-client application does that in its own way. Actually Plan 9 forces everybody providing a service to understand 9p and to be able to translate 9p message requests to whatever it means for that service (what does write(bytes) means for a printer? What does write(bytes) means for a screen? what does write(bytes) means for a GPU? Everyone of those should understand a 9p write() message and translate it to whatever service it means) then Plan 9 uses that power to forward requests over the network to remote servers, making easy to use resources in a distributed environment.
The latter does not prevent the laptop from the need of a "printer driver" to actually render something. But the driver can be unified (TTY or PostScript), and the printer object (not exactly like a file) has, well, methods to report options and set options, like the paper tray to use.
Or so I understand.
If we could imagine a network filesystem (spanning many hosts) full of Erlang objects which can receive and send data, it would be somehow similar.
I think, in Plan9 philosophy, if the desktop has a driver and it is started in the current namespace, it is represented as a file too (like /dev/my-printer/print-pdf). But it quickly becomes confusing for me:
1. Nowadays we can represent the essence of this approach with FUSE and SSH/SSHFS. Sadly, nobody does: local servers (i3, dbus, ..., vscode) use domain sockets and client executables, probably due to the lack of private namespace support by default.
2. The difference between hypothetical "/dev/my-printer/print-pdf" and almost-like-real-world "my-printer-print-pdf /dev/my-printer" looks similar to binding the first argument in OOP-style vs the explicit C-like call syntax.
>1. Nowadays we can represent the essence of this approach with FUSE and SSH/SSHFS.
These suck hard against 9p and factotum. Not even close, Linux and BSD's are jokes against what you can achieve with plan9/9front on networking whole componentes. You can run remote processes seamlessly.
The important point is that "everything is a file" is just a short way to say "everything is a file system". Your interface is not a file descriptor to which you read and write, but a whole tree where there are different files on which you can perform the operations defined in the 9P protocol (create/read/write/...). For example, in the windowing system, you open a file to create a new window, and the new window will have associated a directory with files that represent the screen, mouse and keyboard (and the process running in that window will work with those files exactly as it does with native devices).
You can have a look at the man pages (sections 3 and 4) to see how these filesystems work.