Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Uniformity enables composition

Type compatibility enables composition. That is, given functions `foo :: A -> B` and `bar :: B -> C`, you can form the composite `bar . foo :: A -> C`. Unix provides a very simplistic solution that guarantees type compatibility (all I/O is byte stream I/O) at the price of creating other problems (what should be the result of `lseek()`ing a socket?).



Unix is the case where A == B == C. e.g. Pipes are an algebraic monoid (not monad).

I noted in my message that Unix polymorphism isn't perfect, and comes with the costs of serialization and escaping. However, I challenge anyone to design something better with types. It's not like people haven't tried.

From Alan Perlis: "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures."

That is the essence of Unix (and Lisp for that matter). You don't want A, B, and C; you want just A, and then 100 functions on it that can be composed.


> Unix is the case where A == B == C. e.g. Pipes are an algebraic monoid (not monad).

Who said anything about monads? I only established the conditions for composition to be possible. Composition is the binary operation of a category, and, while every monoid is a category in a very trivial way, there are categories with more interesting structure. But, categorical blablabla aside, what matters is that making everything a byte stream isn't the only way to make things composable.

> From Alan Perlis: "It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures."

Well, Perlis is wrong on this one. It is better to have types and operations that reduce the number of ways in which your program can possibly fail.


But the point is that types don't belong that the OS level. You can have your type composition in user space, at the language level -- what's the problem with that? Haskell and OCaml run on Unix just fine.

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.


> But the point is that types don't belong that the OS level. You can have your type composition in user space, at the language level -- what's the problem with that?

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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: