为什么getArgs和getProgName IO操作?

ice*_*ime 21 io haskell referential-transparency command-line-arguments

我是一个完整的新手,目前正试图通过"让你学习哈斯克尔为大好 " 来学习Haskell .我已经到达了解释如何使用命令行参数的部分,而且有些事情让我烦恼.

根据我的理解(和haskell.org的定义),动作是为了封装副作用.命令行参数是程序的给定实例的不可变输入,那么有什么意义getProgName :: IO String而不是getProgName :: String?不同之处:阻止纯函数调用的重点是getProgName什么?

更新

到目前为止,我对这个问题有了很好的答案.我接受Don Stewart是最简单和最简洁的,但Conal(及其相关的博客文章)绝对值得一读.

Don*_*art 25

首先,getArgs可以在运行时更改.见withArgs.

其次,getArgs并且getProgName属于一个有趣的不纯计算类 - 它们在程序运行期间被认为是常量,但是,它们在编译时不是可用的值,并且它们从一个程序运行变为另一个程序运行.它们没有干净的外延.

参见前面的讨论,其中讨论了 getArgs和浮点计算.甚至minBound/maxBound都可以被认为是在这个类中.


Con*_*nal 24

为了回答这些问题,你需要一个基础:这是什么意思,一个表达式e的类型是t?您可以为基元提供任意答案getProgName,但您不必这样做.相反,看一下表达式和类型的含义.假设表达式e具有类型t,表示的值e(即,e作为数学值的含义)属于由表示的集合t.

现在考虑t == String.我们想要String有什么意义?同样,这里有很多选择余地.然而,选择具有最简单数学定义的有用候选者有很多优点.在Haskell String == [Char],所以我们其实是在讨论的意义[]Char 最有力的候选简单,我知道的是[]代表名单(序列),并Char表示字符,因此该String表示的字符序列,即"弦".

选择String意味着字符串,现在我们可以询问它是否可能getProgName :: String.如果是这样,则其含义getProgName必须是一系列字符.但是,没有单一的字符序列可以捕获背后的意图getProgName.(编辑:据推测,getProgName当它出现在不同命名的程序中时,你想要产生不同的字符串.)因此,我们必须选择不同的类型,例如(但不一定)IO String,或者我们必须选择更复杂的含义String.后一种方式可能起初看起来很吸引人,直到你考虑到深层含义.纯函数(更准确地说是"指示性")编程支持实用,严格的推理,这要归功于使用简单的含义,如序列而不是复杂的含义,如来自某种环境的函数,包括操作系统,机器执行上下文.

有关密切相关的评论和讨论,请参阅博客文章Haskell中的纯度概念.

编辑:我认为Peter Landin(Haskell的祖父)用他对"外延编程"(或"真正的函数式编程")的定义表达得最好,他建议将其作为"声明性"和"功能性"编程等模糊术语的实质性替代. .有关参考,引文和简短评论,请参阅帖子中的这个评论是否是一个纯粹的函数式语言?.

  • 为了扮演恶魔的拥护者,您如何看待罪恶的功能?甚至(+)?这些对于您正在运行的硬件来说都是迟到的,因此,例如,英特尔和AMD之间的罪可能会有所不同. (3认同)
  • @augustss:我很惊讶和失望地得知Haskell的数字类型确实具有语言定义(与实现无关)的语义. (3认同)