首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >纯粹的代码和不纯的代码?I/O数据类型相关

纯粹的代码和不纯的代码?I/O数据类型相关
EN

Stack Overflow用户
提问于 2015-10-10 17:48:50
回答 1查看 203关注 0票数 0
代码语言:javascript
复制
name <- getLine

下一段是关于这一行是如何工作的。有人能给我解释一下这意味着什么吗?提前谢谢你。

getLine在某种意义上是不纯的,因为当执行两次时,它的结果值不能保证是相同的。这就是为什么它受到IO类型构造函数的污染,我们只能在I/O代码中获取这些数据。而且,由于I/O代码也受到了污染,任何依赖于受污染I/O数据的计算都会有一个受污染的结果。 当我说“受污染”时,我并不是说我们再也不能在纯代码中使用I/O操作中包含的结果。不,我们将I/O操作中的数据绑定到名称时暂时不污染它。当我们指定名称<- getLine时,name只是一个普通的字符串,因为它代表了框中的内容。

EN

回答 1

Stack Overflow用户

发布于 2015-10-10 17:59:08

这一段暗示了这样一个事实,即您不能在具有“纯”类型的函数中使用getLine,而不需要在其中出现IO monad。如果我们试着跑

代码语言:javascript
复制
lineLength :: Int -> Int
lineLength n = n + length getLine

编译器会抱怨,因为length需要一个String (或任何其他列表类型),但是getLine是一个IO String。所以有一种类型错配。

但这并不意味着lengthgetLine不能组合。

代码语言:javascript
复制
lineLength :: Int -> IO Int
lineLength n = do
    line <- getLine
    return (n + length line)

在上面,我们从line :: String暂时“删除line :: String”,以便length可以应用到它,n添加到结果中。但是,我们不得不使用return将纯Int结果转换为IO Int

注意IO也是如何在函数签名中结束的:这是不可避免的。在Haskell中,如果一个函数做了一些不纯的事情,比如使用IO,那么类型系统就会强制您在类型中使用IO。这是引号所指的“污点”:一旦您使用了带有IO类型的不纯函数/值,那么您必须在自己的代码类型中使用IO,而相应的任何调用者都必须使用IO。杂质必须在类型特征中传播。

这也意味着,如果您看到f :: Int -> Int,您可以依赖一个事实,即编译器证明了函数是纯的:它将为相同的输入返回相同的结果。(有几种低级别的方法可以避免这种情况,但它们不适合在常规代码中使用。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33057111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档