在Haskell中使用IO时,难以将元素附加到列表中

n00*_*00b 0 io haskell list

我有一个整数列表,我需要在不同的时间附加元素.

let xs =[]::[Int]
Run Code Online (Sandbox Code Playgroud)

通常将元素附加到此将是:

1:xs
Run Code Online (Sandbox Code Playgroud)

但是当在函数中使用IO时,它似乎不在do块中工作并且给出错误,并且

let xs = [1]
let xs=(2:xs)
Run Code Online (Sandbox Code Playgroud)

导致无限列表如[1,2,2,2,2,.....]我该怎么做才能纠正这个问题?

sha*_*ang 7

你好像对Haskell中的列表有一个基本的误解.列表始终是不可变的,因此无法将新元素添加到现有列表中.即您只能创建新列表.

因此,a:b操作员从不向列表添加元素,而是创建新列表,其中a第一个元素是现有列表b.

当你说:

let xs = 2 : xs
Run Code Online (Sandbox Code Playgroud)

你说这xs是一个列表,其中第一个元素是2,列表的其余部分xs本身,从逻辑上导致2的无限列表.在这个问题的背景下,你是否在IO monad中是无关紧要的.

因此,鉴于上述情况,您需要做类似的事情

let xs1 = [1]
let xs2 = 2:xs1
let xs3 = 3:xs2
Run Code Online (Sandbox Code Playgroud)

但当然,这与简单的做法相同

let xs3 = [3,2,1]
Run Code Online (Sandbox Code Playgroud)

所以你真的需要提供一些关于你想要建立什么类型的列表以及原因的更多背景信息.


Tik*_*vis 5

在Haskell中,let默认情况下绑定是递归的.所以xs第二行中的两个引用自己.解决方案是影响xs绑定:

let xs = [1]
let xs' = 2:xs
Run Code Online (Sandbox Code Playgroud)

请记住,Haskell不允许变异.所以第二个let绑定并不意味着改变值xs- 这意味着创建一个恰好也被调用的新变量xs.

只是为了澄清:xs'完全是分开的xs.Haskell允许您使用'变量名.xs'这里可以很容易xs2.该'的发音是"黄金"(例如EXE文件素)和那里的东西像数学拍摄x,x'并且x''是常见的.

附注:: 前缀列表; 追加意味着将元素放在最后.

另外,你的let xs = 2:xs结果[2,2,2...]而不是[1,2,2,2...].

  • 我认为真正的问题是你没有以正确的方式思考这个问题.每次你有一个新的'let`,你就会创建一个*new*变量,而不是改变前一个变量.Haskell允许这个新变量与旧变量具有相同的名称(阴影),但是你不应该这样做.如果你真的必须有这样的单独步骤,请将每个列表命名为不同的名称. (6认同)