I'm pretty uninformed about libffi but can it help with kind of module interoperability? I've used it to get Ruby to call C functions. I would guess that it could be used for other dynamic languages to call compiled functions such as JS to Haskell like the OP seems to be desiring. Is this true?
I think the problem is more around signatures, actually. If we can find the code, we know how to call it (libffi makes that easy) but how do we expose the library interface?
Clang modules takes some steps towards that for native code. On the JVM, everything is a Java class in the end, with Java type signatures for its methods (which can point to other Java classes, and so on) so rich cross language interfaces are a solved problem.
Other posters have raised concerns about garbage collection or "losing all of the nice features of whatever languages you're using" but I have some doubts:
* Interface definition languages like Protobuf or Cap'N'Proto actually show us just how much commonality there is across languages. They provide for many features that are fancy relative to C but not really relative to anything else; and the interfaces are definitely useful.
* Many languages with sophisticated type systems work by compiling object code and then appending an interface file to capture the type information. Haskell, Rust, OCaml and many others do this, essentially treating every module as foreign code with additional type information.
A good cross language module system would need those features that make sense across languages -- parameterized array and map types among them -- and this does mean, not every piece of Python (for example) would make sense as a Rust library. Consider the interface of the linked project, though -- only `mineBlockFrom` needs to be rethought to be typable in a way that makes sense across many languages.
Most languages have some degree of interoperability with C, but that means losing all of the nice features of whatever languages you're using, even if they're implemented on both ends.
The hardest part of combining two languages through a foreign function interface (eg Ruby/C using libffi) is making their garbage collectors work together. You basically have to either use a single garbage collector across the language boundary, like the family of languages implemented on the JVM do, or require one or both of the languages to implement GC-less memory management, like in the Ruby/C case.