[英]Why is the output of this Haskell function an IO String instead of a String
我正在通过learningyouahaskell.com学习Haskell,并想在完成输入/输出模块之前测试一些概念。 尽管看起来很简单,但我仍无法用谷歌或笨拙的方式解决这个问题。
当我尝试运行以下代码时
getName = do
name <- getLine
return name
即使name绝对是String
, getName
的输出也将成为IO String
类型而不是String
类型的元素
通过阅读文档和其他StackVverflow的问题,当我将getName
声明为函数时(当我直接在main
上直接使用bind <-操作时,就没有问题了),我无法弄清楚为什么会发生这种情况。
return
函数在概念上与C ++,Java和Python等语言中的return
函数并不相同。 return :: Monad m => a -> ma
接受a
(这里是String
),并产生ma
(这里IO a
)。
该do
记号是syntacticual糖。 如果我们对声明不加糖,那么您写道:
getName = getLine >>= (\name -> return name)
或更清洁的:
getName = getLine >>= return
因此,绑定函数(>>=) :: Monad m => ma -> (a -> mb) -> mb
具有第一个操作数ma
和第二个功能a -> mb
并产生mb
。 由于getLine :: IO String
是IO String
,因此这意味着m
与IO
相同,而a
与String
相同。 return :: Monad m => a -> ma
,清楚地表明b
与a
相同。
那么这里的IO
是什么。 一个经常使用的隐喻就是食谱之一 。 在此隐喻中, IO a
是一组指令,当您遵循这些指令时,将获得a
。 但这并不意味着该食谱是a
。
(>>=)
这里基本上是说,左手边有一个制作a
的配方,右手边有个将a
转换成要制作b
的配方的函数,因此我们可以构造一个要点b
的配方与这两个。
人们经常会问如何解开一个a
出的IO a
,但在概念上它使没有太大意义。 您不能从食谱中“解包”蛋糕来制作蛋糕。 您可以按照说明做蛋糕。 遵循指示是main
最终操作。 因此,我们可以构造一个主要的(长)配方。 但是我们不能解开价值观。
严格来说,有一个函数unsafePerformIO :: IO a -> a
可以做到这一点。 但是强烈建议不要使用它。 Haskell中的函数应该是纯函数,这意味着对于相同的输入,我们总是检索相同的输出。 getLine
本身是纯函数,因为它总是产生相同的配方( IO String
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.