There are some ways that functional programming languages still lack when compared to C; in particular they fail to export their constructs for use in other languages.

Let us consider Haskell as an example, which is a good language.


Typeclasses can be compiled to record-passing; instead of a typeclass

class Ord a where compare : a -> a -> Ordering

sort : Ord a => [a] -> [a]

One could write sort to take compare : a -> a -> Ordering as an argument, viz.

sort : (a -> a -> Ordering) -> [a] -> [a]

Then this sort function could be exported and called via FFI.

However, in practice, typeclasses are not compiled into object files or shared libraries for use in other languages. Worse, GHC produces faster code when it can aggressively inline and specialize typeclass functions across modules. So the sort exported in an object file would be a degraded, less performant version.

Instance Resolution

Instance resolution in GHC is already relatively ill-documented, and in any case nothing is exported in the way that C puts its procedures into object files.

QuickCheck Instances

There is great power in QuickCheck. Suppose we write a function ncdf :: Double -> Double. Then we can prod it with:

> quickCheck $ \x -> ncdf x > 0 && ncdf x < 1 +++ OK, passed 100 tests.

Double implements Arbitrary and so a function of type Double -> Bool is testable.

I'm not sure how such a thing would work across languages, but in any case it shows something truly impressive about Haskell that is not embedded in object files à la C.

Derived Instances

GHC can derive functor instances for types defined in Haskell; it is unclear to me how such a capacity would be exported.

SYB-style generics

Haskell and other ML descendants admit SYB-style generics: one can use the structure of an algebraic data type to implement functions on values of that type.

Dhall's Haskell implementation is a particularly impressive example of this; one writes an algebraic data type in Haskell and without any effort from the user, there is a parser and typechecker for the corresponding Dhall type.

However, this particular style of programming is efficient because of GHC's simplifier. One could in theory export generic functions, but cross-language generics would have degraded performance using current compiler toolchains.

Rust's macros are likewise impressive, but they are not exported in any way.

New Compiler Designs

Compiler pipelines go from source to assembly; perhaps they should also offer library functions for manipulating generics.

Consideration of object file formats (for instance) that encode more than procedures would no doubt be fruitful—it has already been pioneered by C, which has hardly any competitors!