Computation and State Machines (2008) [pdf]
lamport.azurewebsites.net
lamport.azurewebsites.net
* https://news.ycombinator.com/item?id=11854376 - June 7, 2016 (6 comments)
* https://news.ycombinator.com/item?id=13153846 - Dec 11, 2016 (24 comments)
* https://news.ycombinator.com/item?id=18012672 - Sept 18, 2018 (8 comments)
My question is: Turing Machines are easily and intuitively understood as state-machines. But what about Functional Programming? I thought functional programs have no 'state'. What is the simplest way to explain how functions are also state-machines?
Here is a complete specification of a state machine's transitions:
f LightOff OnPressed = LightOnDimmed
f LightOnDimmed OnPressed = LightOnMedium
f LightOnDimmed OffPressed = LightOff
f LightOnMedium OnPressed = LightOnBright
f LightOnMedium OffPressed = LightOff
f LightOnBright OnPressed = LightOnDimmed
f LightOnBright OffPressed = LightOff
Here is a Haskell function which models the above state machine's transitions: f LightOff OnPressed = LightOnDimmed
f LightOnDimmed OnPressed = LightOnMedium
f LightOnDimmed OffPressed = LightOff
f LightOnMedium OnPressed = LightOnBright
f LightOnMedium OffPressed = LightOff
f LightOnBright OnPressed = LightOnDimmed
f LightOnBright OffPressed = LightOfffoldr f LightOff input_stream
Where are the previous inputs and results (= state) of the calculation stored which allow the next calculation depend on previous results? In some variable?
Here's a simple example which I'm not saying proves my point but I have a question about:
I have a program which calculates the average temperature of the year so far. You input today's temperature into it and it calculates and outputs the new updated average. If it is implemented as a functional program I can see how it can be given a time-series as input and it outputs the average.
But today is a new day and I have a new temperature measurement which I give to my program. If it really is something I could call a "state-machine" it should be able to calculate the new average for me. But to do that it would need to have all the previous inputs held somewhere in its "state".
Is there a functional program that can do that and give me the updated average temperature? Examples in JavaScript please if possible. Not everybody understands Haskell. Or is it something that can be done only in Haskell?
function updateAverage(averageAsOfYesterday, todayTemp, todayDayOfYear) {
yesterdayDayOfYear = todayDayOfYear - 1
sumOfAllTempsUpToAndIncludingYesterday = yesterdayDayOfYear * averageAsOfYesterday
return (sumOfAllTempsUpToAndIncludingYesterday + todayTemp) / todayDayOfYear
}# foldl
state = LightOff
while data {
input = get_next(data)
state = f(state, input)
}I want you to translate the above state machine to a Turing Machine, or demonstrate in any way how a TM is a tool or model which brings any kind of clarity or simplicity to any modelling, design, compilation or coding activity.
The state does not lies in the code, but in the set of variables. Once a specific combination of variable/values is known, so is the output.
The point of FP to me is that you can hide the state from the programmer. As far as the programmer, or the reader of the source-code is concerned there is no state and no state-machine. Lambda Calculus is a specific "model of computation" which does not look like a "state-machine" to me. So calling it a "state-machine" is a bit misleading.
Yes you need a state-machine to "simulate" Lambda Calculus. But how it is implemented, the programmer does not need to know or care. All they see is functions and no state, at least no state they could directly modify.
The program state (if any) and runtime state are two separate things. And if you the programmer can not modify the state of the state-machine, then it is not a state-machine for you.
In functional languages (especially pure ones) there is the notion of "reductions" which are rewrite rules for the language. So in Scheme (to pick a concrete language) an expression like:
(+ 5 2)
Is reduced by applying the addition operation: (+ 5 2) => 7
Or (with a suitable definition of factorial to continue his example): ;; using his Program 3 in Scheme instead of C
(define (factorial i)
(if (= i 1)
1
(* i (factorial (- i 1)))))
(factorial 7) => (if (= 7 1) 1 (* 7 (factorial (- 7 1)))) ;; because we substitute 7 for i
=> (if #f 1 (* 7 (factorial (- 7 1)))) ;; reducing (= 7 1) => #f
=> (* 7 (factorial (- 7 1))) ;; reducing (if #f e_t e_f) => e_f
=> ...
Each of these arrived at by applying a reduction rule (in this case there's only one reduction rule available at each point).This is analogous to his discussion of BNF grammars. The state transitions are moving from an expression e to an expression e' where some reduction rule has been applied to e.
EDIT: Grammar and comments describing application of reduction rules.
I don't think anybody would try to model a state-machine by making each state-change they want to model a call to a sub-function. The engine evaluating the function-expressions has its state but the functional program itself does not, it just has it code, arguments, and result. It can be in one of the states
1. Not Called 2. Calculating the result 3. The result has been calculated.
> 1. Not Called 2. Calculating the result 3. The result has been calculated.
That describes an oracle, not a purely functional program. A program describes a process (whether the program is purely functional or totally imperative). The state of the process can be captured in progress because, well, it's a process. There is a series of steps which are applied to produce the calculated result.
In purely functional programs, that would be the reduction rules. Each application of a reduction rule produces a new state (in essence the remaining computation to be performed).
> The point of FP to me is that you can hide the state from the programmer
Well which is it?
[1] https://en.wikipedia.org/wiki/Abstract_machine#Functional_pr...
The functions are the transitions of the state machine. The datatypes are the rest.
(λ11)(λλλ1(λλλλ3(λ5(3(λ2(3(λλ3(λ123)))(4(λ4(λ31(21))))))
(1(2(λ12))(λ4(λ4(λ2(14)))5))))(33)2)(λ1((λ11)(λ11)))
a state machine.Can a functional program return to its previous state ever? If not I don't think it should be called "state-machine".
It can calculate what should be the next state of some state-machine, but that does not mean it is that "state-machine".
Reducing N may not qualitatively do much from the pedant's point of view, but if one's (formal or informal) analyses tend to scale as O(N*3), reducing N quantitatively may make a difference: between tractable (for formal analysis) or "fits in developers' heads" (for informal analysis) on the one hand, and a big ball of mud on the other.
Mainstream Lisps have all these abstract elements also. The main differences are in data, and environments what constitutes a value; what is a type; what is a variable; what is the lifetime of an object, and the scope of visibility of a binding, ...
In other words, each call to f “updates” the state machine by calculating the next state of the state machine.
Discusses the fundamental role of state machines in computer science.
In computer science, there's an excessive focus on languages, often obscuring the fact that languages all describe state machines.
The document intends to demonstrate how state machines express computation and clarify the concepts underpinning the various languages used to describe computations. It then delves into state machines' function within the sphere of 'correctness' in computer science, drawing on works related to Abstract State Machines by Yuri Gurevich and others.
this is not accurate; some computer programs behave like state machines, but others do not .. not even close
However technically, and pedantically, all programs must behave like state machines.
Btw it looks like it’s the author of the paper, not gpt4 making this confusing point so if one disagrees with the summary it’s a disagreement with the paper.
Here’s a link that covers your specific point: https://softwareengineering.stackexchange.com/a/288063