可以在没有状态的情况下表示任何程序任务吗?


13

这是一个理论问题,但是经过多年的编程之后,我意识到现在是“正常的”命令式技术,主要使用C ++,我发现了函数式编程的另一个领域,在偶然学习JavaScript时偶然发现了这个问题。

这使我想知道您是否可以用一个纯粹的功能且没有状态的不同实现在技术上替换任何完整的面向状态的程序?

这是一个有趣的想法,我必须承认,函数编程的清晰性和优雅性确实让我大吃一惊。


1
一个相关的StackOverflow的答案:stackoverflow.com/questions/3722084/...
jfriend00

是否存在从一个时间点到另一个时间点持续存在的状态,并不取决于您使用哪种编程范例,而取决于您正在编码的问题或任务。如果您要计算一个按钮被点击的次数,那么很显然,有一种状态可以记录该计数器,而使用哪种编码技术都没关系,在此过程中必须有一种状态来跟踪计数。因此,无论您如何编码,该特定任务都无法在没有状态的情况下完成。
jfriend00

6
如果您想讨论状态;如果只针对程序本身,则显然需要状态。听起来您似乎正在考虑可变状态与不可变状态-您可能希望指出问题中的含义。
Billy ONeal

1
这就像询问是否所有程序都可以转换为真正的图灵机一样。从技术上讲,是的,甚至是从数据库保存和加载的程序,但是在图灵机中模拟这种行为变得更加困难。同样,您可能有一个程序,该程序的MVC体系结构中的控制器端已删除,并且您执行了所有调用,尽管如此,它又变得更加难以处理(实际上,您成为了控制器,以使程序成为无状态)。
尼尔

Answers:


17

简短的回答:是的。根据维基百科,艾伦·图灵(Alan Turing)于1937年证明了λ演算与图灵机作为计算的通用模型的等效性。在谈论命令式或有状态编程时,通常会想到图灵机的计算模型,而lambda演算是“纯函数式编程”的数学形式化。

据推测,每个有效的计算模型都能够执行与图灵机相同的计算,反之亦然。这就是所谓的“ 教堂-图灵论题”。但是,由于或多或少的直觉性术语“有效的计算模型”(也许有人将来会发明新的模型?),因此无法证明这一推测。


2
可以将您的同一个论点说成是巡回演出机器的兰巴演算,每个计算都必须具有(或多或少是隐藏的)状态。无论是表示为在代码外部(通过变量)还是在流程内部(通过基于堆栈的函数调用),始终表示为“状态”。
Emilio Garavaglia

3
Lambda演算具有状态。它的约束是状态是不可变的。不可变状态仍然是状态。函数的参数(包括lambda)仍处于状态;假设您希望函数在具有不同参数的情况下具有不同的行为。
Billy ONeal

@emilio声明存在一个等效的基于状态的问题解决方案(如您所述)并不能证明该解决方案不存在无状态版本。
Billy ONeal 2013年

2
@EmilioGaravaglia之后,您要引用的是lambda微积分解释器的状态。在lambda演算中进行推理时,无需推理状态。同样,“可变性”的方面也有所不同。
wirrbel

1
@EmilioGaravglia:命令式编程中的状态一次是存储器配置,此处参数空间由所有可能的存储器值给出,状态一次是一个配置(图灵机的频带)。在lambda演算中编写程序时,没有直接实体,例如存储字段。程序执行是lambda转换的应用。中间步骤可能类似于“状态”,但它们只是具有相同值的等效表达式。求值过程中没有任何变化,只是将表达式重写并处理为“简单”形式。
wirrbel

14

在任何动态系统中,“状态”都是使您的现在受到过去未来的影响的因素(时间的箭头不是数学问题,只是物理约束)。

无论您有“要记住”的东西还是取决于您所做的事情,您都有状态。

没有状态的系统不是“动态的”:它只是组合功能。那可能没有状态,但是-为了产生不同的结果-需要以某种方式提供状态。

现在,根据您引用的计算模型,状态可以显式(以变量的形式)或隐式(以“返回地址”的形式)表示。

当您执行操作时,您fna(fnb(x))将给fnb一个状态,这反过来又会为fna产生一个状态。这是由于x存在一个事实,即在调用fnb之前就已经存在(因此,它来自它自己的“过去”)。

这与“状态退出”或“状态不存在”无关。这是“我在乎”或“我不在乎”的问题。


0

状态是指以一种取决于过去刺激的方式响应当前刺激的能力,而不仅仅是基于当前刺激。

纯粹的功能程序就是功能。因此,对于实际应用,纯功能程序输入一对(old_state * present_stimulus)并输出一对(new_state * present_response)。需要一个外部的,有状态的“循环器”来等待下一个刺激并传播状态。

纯粹的功能性程序本质上不具有状态,并且-不能-直接用于实际应用。

因此,任何面向状态的程序都不能被具有纯功能且没有状态的其他实现替换。


0

只要您不必与外界交互,就可以避免显式的可变状态。

在JavaScript中,为了使您的程序真正发挥作用而不占用处理器周期,您必须修改Dom或Window对象,并且这些API是有状态的。但是我想您可以创建一个包装器,该包装器将Dom和Window对象作为参数传递给JavaScript代码,然后接收一个新的Dom / Window作为输出。这样可以将JavaScript代码与可变状态隔离开。

当然,您仍然依赖状态,因为浏览器窗口和DOM本质上是有状态的。任何交互式应用程序本质上都是有状态的,但是您仍然可以以最小化显式状态的方式构造代码。

一个不同的问题是这是否是一个好主意。甚至Haskell(按设计是一种纯粹的功能语言)也包含“状态”单子,该单子使您可以模拟可变状态。这表明明确的可变状态有时确实是一种理想的模式。


0

考虑一下如何在没有状态的情况下以编程语言实现“状态机”。

您可能实际上可以这样做,但最终将使用函数名作为存储。最终像gobblyday gook一样:

if (sm.atBegining()) sm.start() else if (sm.done()) sm.stop() ) else sm.progress()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.