I've been thinking about structuring servers around FRP [1] and declarative programming for a while now. FRP is based on the notion of events / signals as first class objects and the ability to compose those; it has been gaining popularity for client programming in recent years [2].
For example, on a very high level, an HTTP request signal function might look like this:
request :: Signal Request -> Signal Response
And a database request function might roughly look like this:
requestDB :: Signal Query -> Signal [Record]
Having the basic building blocks, one could imagine building a function to e.g. extract all users:
extractUsers :: Signal Request -> Signal Response
extractUsers = request . createUserQuery . requestDB . showUsers
Similar signal functions could theoretically be constructed for routes, system functions, static files and so on. And since all signal functions are pure, composing those and creating ever more powerful abstractions without having to worry about system state and environment context may be a nicer way of doing server programming.
And since all signal functions are pure, composing those and creating ever more powerful abstractions without having to worry about system state and environment context may be a nicer way of doing server programming.
FRP signals (specifically, behaviors, the dual of events) are most definitely not pure. Yes, the functions which define them are. But the entire point of FRP is to allow one to manage state in a functional context. (Otherwise you could not manipulate a database -- an inherently stateful construct! -- as you do in your example.) You definitely still have to worry about state -- you're just forced to structure it a little better now.
Well, then nothing is pure, since even a declarative, non-FRP, pure program needs to be executed on a stateful CPU with registers and so on.
FRP just deals with time explicitly, i.e. a fold over time over a signal is just as pure as a normal fold over a list (even if the latter is ultimately translated into a stateful loop).
No, you're missing my point; it's not about what happens "under the hood"; it's about the holistic properties of a FRP system. (Also, you don't need to explain FRP to me; I've implemented three FRP systems in two languages.)
A system if stateless by definition iff its observable behavior is independent of its input history over time. (This definition applies to disciplines other than computer science, BTW.) That is not true of any FRP system which generates behavior signals from event signals (as a database does), unless you want to execute said system over fixed data (your "list fold" example), therefore making time irrelevant, making the system non-interactive, and making the example uninteresting to the problem FRP is trying to solve.
Does a FRP description of a system eschew global mutable variables and non-local effects? Yes.
Does a FRP description of a system force state to be handled explicitly? Yes.
Do FRP languages encourage decoupling of state into small pieces? Yes.
Are FRP programs described by referentially transparent pieces? Yes.
Are useful FRP systems as a whole not stateful? Absolutely not.
Purity is, informally speaking, "same output for same input". If you start out with the same database and feed the same input in the same time intervals to a FRP program, the resulting database will always be the same, (i.e. if you view the database as a value).
In the real world, a database is of course stateful, but then again so are CPU registers. There's no fundamental difference.
If you start out with the same database and feed the same input in the same time intervals to a FRP program, the resulting database will always be the same, (i.e. if you view the database as a value).
You realize that's true of, like, every digital computing system ever, right?
is pure. Still, when evaluated on a CPU somewhere a register or a memory location gets mutated, i.e. it produces a side effect. In that sense nothing would be pure.
Yes, that function is pure. Purity is a property of functions.
The system formed by that function being repeatedly applied to the value of DB over time is stateful. Statefulness is a property of systems.
Also, forget about CPU-level stuff. That's a straw man and is irrelevant to the discussion; everyone in this thread is talking about the holistic (i.e. system-level) definition of state, as that is what FRP manages.
Beside, the mathematical mechanism by which a stateful system (the CPU) can be considered to be holistically stateless (a purely functional program) is the exact same mechanism by which a stateless system (a functional description of a state machine) can be considered to be holistically stateful -- that is by the definition I gave above and will repeat below.
Again: the definition of a stateful system is one whose observable behavior is dependent on historical inputs. You are conflating this well-accepted notion of state with the independent concepts of referential transparency, (non)locality, and (non)determinism.
[1] is a good simple explanation of what FRP is about. A DB interaction for example can be viewed as a pure function from a signal of Requests to a signal of Records. Same with files (Signal Path -> Signal FileContents), etc.
For example, on a very high level, an HTTP request signal function might look like this:
And a database request function might roughly look like this: Having the basic building blocks, one could imagine building a function to e.g. extract all users: Similar signal functions could theoretically be constructed for routes, system functions, static files and so on. And since all signal functions are pure, composing those and creating ever more powerful abstractions without having to worry about system state and environment context may be a nicer way of doing server programming.[1] Functional Reactive Programming - http://en.wikipedia.org/wiki/Functional_reactive_programming
[2] http://elm-lang.org