Live data from Hacker News

Exotic Programming Ideas: Module Systems

stephendiehl.com

21–30 of 57 posts

Re: Exotic Programming Ideas: Module Systems

#21
Looking forward to the series! I hope, in one of his "presents", he talks about Lisp conditions and signals, which have also inspired PL/I conditions, and go really back to the idea of an error handler in an operating system.

Unfortunately, Unix (and C) really botched signals by limiting their number in the user space (in particular, they cannot be stacked), and so the idea largely fell out of favor as an error-handling paradigm.

Re: Exotic Programming Ideas: Module Systems

#22
You can do something similar in Rust to ML modules using traits and generic impls as module functors!

https://play.rust-lang.org/?version=stable&mode=debug&editio...

This can be really useful especially as traits with differing concrete types diverge, you can create a unified interface trait object to allow trait objects for things like container classes.

Re: Exotic Programming Ideas: Module Systems

#23
post #3

Other than the syntax, I’m not sure I understand how this is different from any other object-oriented class definition. I suppose the ability to project the module into the local or top-level scope, but that seems more like syntactic sugar than anything meaningful. What am I missing here?

Module signatures may contain types. So you can write a signature like: module type VectorSpace = sig module Field : Field type t val zero : t val (+) : t * t -> t val (*) : Field.t * t -> t end In OOP it becomes hard to write an interface like this simple example, and more complex examples become harder still.

Can you give an example of the value this would provide that isn't provided by generics?

Re: Exotic Programming Ideas: Module Systems

#24
Coming in without much OCaml experience, I don't really think this is a great demonstration of why this construct has value.

I don't really want to read a long form description of the OCaml implementation of modules. I want a comparison to the languages he dismissed at the beginning of the article, and a discussion of why this feature has some value that isn't provided by those languages.

Basically - This feels like a different take on generics to me. There might be a lot of value in how this is implemented when compared to generics in a language like Java/C#/Typescript, but I didn't find that content anywhere in the article...

Re: Exotic Programming Ideas: Module Systems

#25

Zig's compile time execution lets you do similar things I believe. In Zig, structs and modules are equivalent, and type declarations can be manipulated at compile time just like any other value. That, among other things[1], lets you write: fn LinkedList(comptime T: type) type { return struct { pub const Node = struct { prev: ?*Node, next: ?*Node, data: T, }; first: ?*Node, last: ?*Node, len: usize, }; } I wonder if t…

One thing is that OCaml modules are first class objects, so can be constructed at runtime and passed around as variables. But this Zig example, I think, will cover the most common case of functors for creating generics.

(I'm also not sure if Zig does compile-time check if the type T is compatible with LinkedList. OCaml does this type of check, making sure the signature of T fits the requirement of the functor LinkedList. The module T may have certain functions, for example a compare function associated with T to ensure sorting of the elements in your data structure.)

Re: Exotic Programming Ideas: Module Systems

#26
On the topic of modules, I recommend reading about modules in Newspeak: https://bracha.org/newspeak-modules.pdf

Modules (which are just top level classes and contain nested classes) have no import statement and no hard linked external dependencies. When you instantiate the module (~class) you pass in dependencies it needs.

Re: Exotic Programming Ideas: Module Systems

#27
post #3

Other than the syntax, I’m not sure I understand how this is different from any other object-oriented class definition. I suppose the ability to project the module into the local or top-level scope, but that seems more like syntactic sugar than anything meaningful. What am I missing here?

As another answer pointed out, a class in OOP is supposed to implement only one type and operations on it. It works in many cases, but sometimes it does not fit naturally the problem at hand.

Modules relax this single-type requirement, and let you define multiple types in it, which makes certain things more natural to express, without a need to create multiple shallow classes or manager-like classes.

Also, functors (i.e. "module functions") in the OCaml module system allows generics, when a module is essentially parameterized by one or more other modules.

Re: Exotic Programming Ideas: Module Systems

#28
post #21

Looking forward to the series! I hope, in one of his "presents", he talks about Lisp conditions and signals, which have also inspired PL/I conditions, and go really back to the idea of an error handler in an operating system. Unfortunately, Unix (and C) really botched signals by limiting their number in the user space (in particular, they cannot be stacked), and so the idea largely fell out of favor as an error-handl…

I worked for Prime (minicomputers) as a youngster in the early 80's. They supported PL/I and many parts of the OS (Primos) were written in a systems dialect of PL/I they called PLP.

The PL/I condition mechanism was an integral part of the OS and fault handling. For example, a floating point exception or integer overflow was detected by hardware, caused a fault, the information from the fault was packaged into a condition frame (an extended stack frame), and a condition was raised. The OS looked backward through the stack looking for an "onunit" (aka condition handler) that handled this condition - basically like try & except.

Condition handlers were very flexible, with the option to partially handle the condition then let it continue with older frames, ignore the condition in this handler and let it continue, or completely handle it.

If no running program had a handler for a condition, the default OS handler would run, which often raised a new condition and printed an error message. If the problem causing the error was corrected (for example, some files were deleted from a full disk), you could use the REN (re-enter) command to return from the disk full condition and the system call causing the condition would be automatically re-tried, sort of like when EINTR occurs on a system call and it has to be (manually) retried.

Instead of using numbers, conditions had arbitrary names and arbitrary data could be associated with a condition.

In hindsight it was very similar to Python's try/except/finally error handling mechanism. There was a condition called "cleanup$", which was executed whenever a procedure was aborted because of a stack unwind to allow it to close files, delete temp files, etc.

I wrote an emulator for the Prime and you can see all this with:

telnet em.prirun.com 8001

There are all kinds of manuals online too, including a full PL/I implementation, all from the 80's and early 90's.

Re: Exotic Programming Ideas: Module Systems

#30

Earlier quoted context omitted.

Module signatures may contain types. So you can write a signature like: module type VectorSpace = sig module Field : Field type t val zero : t val (+) : t * t -> t val (*) : Field.t * t -> t end In OOP it becomes hard to write an interface like this simple example, and more complex examples become harder still.

Can you give an example of the value this would provide that isn't provided by generics?

One thing the example shows is the classic problem with OO's mechanism, namely binary functions. For a given class, something like `+` is impossible to implement elegantly, it has to bias one operand over the other -- after any syntactic sugar, it's always `arg1.op(arg2)`. Module functors resemble true ADTs more, in that they do not dispatch from a live instance of the datatype.
Post reply on HN