> Can anyone explain why not "functional core, functional shell"? Is this partly because the shell has to mostly interact with things like UI APIs, file system APIs, network APIs and database APIs that are usually implemented in an imperative way already so you'd make your life harder this way? What if the APIs were written in a functional style?
Fundamentally the user isn't functional - if you ask them what they want to do they'll say different things at different times. You can have a 100% purely functional programming language that works like a calculator (with no memory) - the user can put in expressions and the language will evaluate them - but generally users want their language to be able to do things that are non-idempotent and non-time-symmetric and so on. You can, and should, push that part to the edge, but it needs to be there somewhere.
What you say is true, but FP has many different ways of dealing with user input, environment, IO, that are no more complex than imperative procedures (arguably the FP equivalent is simpler).
Such as? Haskell-style IO types have no real denotational semantics (they don't even have a notion of equality), they're useful for jamming imperative instructions into an expression model but they don't actually make them any less imperative, and the only other models of user input I've seen are even more obtuse and harder to work with. If something can only be understood operationally, representing it as an imperative procedure is probably the least bad approach IME (and diving into a "the C language is purely functional" style tarpit is far worse; look at SBT for where that leads).
Not an issue with F#. It’s trivial to exit ’purely functional’ domain, write it like ’pythonic C#’ and still end up with a program that is correct out-of-the-box.
Fundamentally the user isn't functional - if you ask them what they want to do they'll say different things at different times. You can have a 100% purely functional programming language that works like a calculator (with no memory) - the user can put in expressions and the language will evaluate them - but generally users want their language to be able to do things that are non-idempotent and non-time-symmetric and so on. You can, and should, push that part to the edge, but it needs to be there somewhere.