Programming languages 我应该如何管理新语言设计中的副作用?

Programming languages 我应该如何管理新语言设计中的副作用?,programming-languages,haskell,side-effects,Programming Languages,Haskell,Side Effects,所以我现在正在研究一种新的编程语言。受并发编程和Haskell的启发,该语言的主要目标之一是管理副作用。或多或少,每个模块都需要指定允许哪些副作用。因此,如果我正在制作一个游戏,图形模块将无法执行IO。输入模块将无法绘制到屏幕。人工智能模块需要完全纯净。游戏的脚本和插件可以访问非常有限的IO子集来读取配置文件。等等 然而,副作用的构成并不明确。我正在寻找关于这个主题的任何想法或建议,我想用我的语言来考虑。以下是我目前的想法 有些副作用是显而易见的。无论是打印到用户控制台还是发射导弹,任何读取或写

所以我现在正在研究一种新的编程语言。受并发编程和Haskell的启发,该语言的主要目标之一是管理副作用。或多或少,每个模块都需要指定允许哪些副作用。因此,如果我正在制作一个游戏,图形模块将无法执行IO。输入模块将无法绘制到屏幕。人工智能模块需要完全纯净。游戏的脚本和插件可以访问非常有限的IO子集来读取配置文件。等等

然而,副作用的构成并不明确。我正在寻找关于这个主题的任何想法或建议,我想用我的语言来考虑。以下是我目前的想法

有些副作用是显而易见的。无论是打印到用户控制台还是发射导弹,任何读取或写入用户拥有的文件或与外部硬件交互的操作都是副作用

其他的更微妙,这些是我真正感兴趣的。这些将是像获取随机数、获取系统时间、睡眠线程、实现软件事务性内存,甚至是一些非常基本的事情,比如分配内存

与其他为控制副作用而构建的语言不同(看看你的Haskell),我希望我的语言设计实用。对副作用的限制有两个目的:

  • 帮助分离关注点。(没有一个模块可以做所有事情)
  • 对应用程序中的每个模块进行沙箱处理。(任何模块都可以用作插件)

考虑到这一点,我应该如何处理“伪”副作用,如我上面提到的随机数和睡眠?我还可能错过什么?我可以用什么方法来管理内存使用和时间作为资源?

认真观察内存使用和时间的使用,以控制副作用。

副作用对世界上任何事物都有影响,而不是返回一个值,即改变一些在函数之外以某种方式可见的东西

纯函数既不依赖于也不影响函数调用范围之外的任何可变状态,这意味着函数的输出只依赖于常量及其输入。这意味着,如果使用相同的参数调用函数两次,则无论函数是如何编写的,都可以保证两次得到相同的结果

如果有一个函数修改已传递的变量,则该修改是一个副作用,因为它是函数的可见输出,而不是返回值。一个不是无操作的空洞函数肯定会有副作用,因为它没有其他影响世界的方式

函数可以有一个私有变量,该变量只对它读取和修改的函数可见,调用它仍然会产生副作用,即改变函数将来的行为方式。纯意味着任何类型的输出只有一个通道:返回值

完全可以生成随机数,但必须手动传递随机种子。大多数随机函数保留一个私有种子值,该值在每次调用时都会更新,以便每次都获得不同的随机值。下面是一个Haskell代码段,使用:

每个随机函数都返回随机化值,并返回一个带有新种子的新生成器(基于上一个种子)。要每次获得一个新值,必须传递新生成器链(gen1、gen2、gen3)。隐式生成器只使用一个内部变量来存储gen1。。背景中的值

手动执行此操作是一件痛苦的事情,在Haskell中,您可以使用状态monad使其变得更容易。您可能希望实现一些不那么纯粹的东西,或者使用单子、箭头或唯一性值等工具将其抽象出来

获取系统时间是不纯的,因为每次您询问时,时间可能不同

睡眠是模糊的,因为睡眠不会影响函数的结果,而且你总是可以在繁忙的循环中延迟执行,这不会影响纯净度。问题是,睡觉是为了别的事情,这是一种副作用

纯语言中的内存分配必须隐式进行,因为如果可以进行任何类型的指针比较,显式分配和释放内存都是副作用。否则,创建两个具有相同参数的新对象仍然会产生不同的值,因为它们具有不同的标识(例如,通过Java的==运算符不相等)


我知道我已经讲了一些,但希望这能解释什么是副作用。

如何描述和控制效果的问题目前占据了编程语言中一些最优秀的科学头脑,包括哈佛大学的人。据我所知,大卫·吉福德(David Gifford)和皮埃尔·朱维洛特(Pierre Jouvelot)在1987年开始使用FX编程语言完成了这方面最雄心勃勃的开创性工作。这是一个非常有趣的问题,它代表了我所经历的一个阶段,坦率地说,我已经超越了这个阶段

我记得卡尔·休伊特(Carl Hewitt)在讨论演员形式主义时讨论过这一点。他将其定义为一种方法,该方法给出的响应仅仅是其参数的函数,或者可以在不同的时间给出不同的答案

我说我超越了这一点,因为它使语言本身(或计算模型)成为主要主题,而不是它应该解决的问题。它基于这样一种思想,即语言应该有一个正式的底层模型,以便其属性易于验证。这很好,但仍然是一个遥远的目标,b
randomColor              :: StdGen -> (Color, Int, StdGen)
randomColor gen1         = (color, intensity, gen2)
 where (color, gen2)     = random gen1
       (intensity, gen3) = randomR (1, 100) gen2