I just try to compile Frama-C (
http://frama-c.com) with the option -no-app-funct in order to discover where/why we need applicative functors (I knew that we use them somewhere).
I found three different patterns:
1) module M = F(G(X))
Without applicative functors, we get the error "The parameter cannot be eliminated in the result type. Please bind the argument to a module identifier.". That is easy to fix by introducing an intermediate module.
2) module F(X:...) = G(H(X))
Without applicative functors, we again get the error about parameter elimination. But I see no workaround to eliminate it without changing the signature of F. So IMHO that is a use case where applicative functors are useful.
3) type t = F(X).t
type u = { a: t }
These declarations are in a single .mli file without a corresponding .ml file. G(X).t is an abstract type. Generators of values of type u are in a module F while users of type u are others modules. Also we have to solve an usual issue with mutual dependencies between F and its users. But the type u is one of the most useful type in Frama-C. Thus standard solution to the mutual dependencies issues which use polymorphism or functor are too heavy here. That is the lightweight solution that we found.
To summarize:
- case 1 may be easily solved by writting 2 lines of code instead of 1
- case 2 and 3 may be circumvented for sure, but the solutions that I have in mind are heavy
To conclude, there are only few use case where applicative functors are useful in an application like Frama-C (where there are thousands of functor applications). But IMHO that are enough cases to answer: yes applicative functors are (sometimes) useful.