我无法弄清楚为什么我得到两个不同的结果,但我确定它与IO我有所关系,我开始讨厌!
例如:
ghci> x <- readFile "foo.txt"
ghci> let y = read x :: [Int]
ghci> :t y
y :: [Int]
Run Code Online (Sandbox Code Playgroud)
现在,当我创建该文件并执行相同的操作时,它出现了IO [Int]吗?
foo.txt 是一个仅包含以下内容的txt文件: 12345
有人可以向我解释一下吗?因为我要抢购它!
感谢您的任何见解!
清楚Haskell在IO产生值的操作和值本身之间的区别.
在Haskell中对IO的一个很好的参考,不希望你想知道monad的理论基础是sigfpe的 IO Monad对于那些根本不关心的人.
请注意,这是他假设你不关心的monad理论位.他假设你关心做IO.这不是很长,而且我认为这对你来说非常值得一读,因为它明确了一些你不知道的"规则",因此引起了你的不满.
无论如何,在你的代码中
x <- readFile "foo.txt"
Run Code Online (Sandbox Code Playgroud)
该readFile "foo.txt"位具有类型IO String,这意味着它是一个产生String的操作.执行此操作时x <- readFile "foo.txt",您将使用它x来引用它生成的String.注意输出x和产生它的操作之间的区别readFile "foo.txt".
接下来让我们来看看y.您可以定义let y = read x :: [Int],所以y是INTS的列表,如您指定.但是,y与定义它的整个块不同.
example = do
x <- readFile "foo.txt"
let y = read x :: [Int]
return y
Run Code Online (Sandbox Code Playgroud)
在这里example :: IO [Int],虽然y它本身有类型[Int].
如果你来自命令式语言,这一开始就令人沮丧 - 你已经习惯了能够使用在你使用值的任何地方产生值的函数,但是你已经习惯了那些允许执行任意IO操作的函数.
在Haskell中,您可以使用"纯"函数(不使用IO)而不是IO操作来执行任何您喜欢的操作.Haskell程序员看到返回值的IO操作和只能在其他任何地方使用的纯函数之间存在差异.
这意味着您最终可能会陷入笨拙的IO monad中,并且您的所有函数都充满了IO数据类型.这很不方便你编写凌乱的代码.
首先在不使用外部(文件或用户)数据的情况下完全解决您的问题:
这意味着在你的程序中,我认为你不应该写任何readFile或其他IO代码,直到你差不多完成.
这是一个完全不同的工作流程 - 在命令式语言中,您可以编写代码来读取数据,然后执行操作,然后编写数据.在Haskell中,最好先编写完成内容的代码,然后在知道功能正确后再编写代码来读取和写入数据.