I don't do kernel programming, so I don't care what kernels do internally. As an application programmer, I want usable APIs. I want an API that makes resource leaks inexpressible, that doesn't let me seek intrinsically sequential streams, etc. Of course, such an API can't possibly be a C API.
> Haskell and OCaml run on Unix just fine.
Haskell has an I/O model that's barely safer than C's. The only improvements are that the `Handle` type is abstract and the `bracket` function is a `try...finally` of sorts. OCaml fares even worse: Can I open a single file for both input and output with just the standard library? In either language, is there a comprehensive solution for manipulating memory-mapped files?
> It would be a mistake to bake types into the OS -- whatever that even means -- because nobody has found the perfect type system.
Making a usable interface to OS services doesn't require a “perfect” type system, just a type system that prevents the most common mistakes that happen when using OS services. OS services are to a large extent about manipulating resources, so substructural types can help a lot.
It would be a mistake to bake types into the OS -- whatever that even means -- because nobody has found the perfect type system. For every type system, there are some things that don't fit in the model. (This reminds me of some theorems in the foundations of mathematics...)
There are even libraries to shell scripts in Haskell and OCaml. If there were some inherent advantage to doing so, they could easily replace shell scripts. But I predict they will not.