【问题标题】:Difficulty in appending elements to a list when using IO in Haskell在 Haskell 中使用 IO 时难以将元素附加到列表
【发布时间】:2012-02-05 08:49:25
【问题描述】:

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

let xs =[]::[Int]

通常在此附加元素会是这样的:

1:xs

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

let xs = [1]
let xs=(2:xs)

产生一个无限列表,如 [1,2,2,2,2,.....] 我能做些什么来纠正这个问题?

【问题讨论】:

    标签: list haskell io


    【解决方案1】:

    您似乎对 Haskell 中的列表存在根本性的误解。列表始终是不可变的,因此无法将新元素添加到现有列表中。 IE。您只能创建新列表。

    因此,a:b 运算符不会将元素添加到列表中,而是创建一个新列表,其中a 是第一个元素,其后是现有列表b

    当你说:

    let xs = 2 : xs
    

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

    因此,鉴于上述情况,您需要执行类似的操作

    let xs1 = [1]
    let xs2 = 2:xs1
    let xs3 = 3:xs2
    

    当然,这和简单的做是一样的

    let xs3 = [3,2,1]
    

    因此,您确实需要提供更多背景信息,说明您想要构建什么样的列表以及原因。

    【讨论】:

      【解决方案2】:

      在 Haskell 中,let 绑定默认是递归的。所以第二行中的两个xs 指的是他们自己。解决方案是隐藏xs 绑定:

      let xs = [1]
      let xs' = 2:xs
      

      请记住,Haskell 不允许突变。所以第二个let 绑定并不意味着改变xs 的值——它意味着创建一个新变量,它恰好也被称为xs

      澄清一下:xs'xs 完全分开。 Haskell 允许你在变量名中使用'xs' 这里很容易成为xs2' 发音为“prime”(例如 exes prime),取自 xx'x'' 等常见的数学。

      附注:: 添加到列表中; appending 表示将元素放在末尾。

      此外,您的 let xs = 2:xs 会生成 [2,2,2...] 而不是 [1,2,2,2...]

      【讨论】:

      • 但是,让 xs' = 2:xs 不会将 2 添加到列表中:S
      • 它创建了一个列表xs',这是将2 附加到xs 的结果。从那时起,只需使用xs' 而不是xs。如果不是递归的let 绑定,你的代码会做同样的事情,除了xs' 将被称为xs
      • 但是当我有 let xs = [1] , let xs' = 2:xs , let xs' = 3:xs 时,这 3 行 xs 只会输出 [3,1],2 不会被前置
      • 我认为真正的问题是你没有以非常正确的方式思考这个问题。每次您有一个新的let 时,您都在创建一个new 变量,而不是更改以前的变量。 Haskell 允许这个新变量与旧变量具有相同的名称(阴影),但您不应该这样做。如果您真的必须有这样的单独步骤,请为每个列表命名不同的名称。
      【解决方案3】:

      为了完整起见,如果您真的想要在 IO monad 中强制“分配”(这就是您的意思),您可以。您将使用可变单元格(“参考”);在 IO monad 中,将是 IORef:

      import Data.IORef
      
      do xs <- newIORef [1]
         temp <- readIORef xs
         writeIORef xs (2 : temp)
      

      但是,这样做会非常不习惯,而且你几乎不想写这样的东西。

      【讨论】:

        【解决方案4】:

        不要让你的列表是递归的吗?

        let xs = [1]
        let foo=(2:xs) -- non-recursive
        

        【讨论】:

          猜你喜欢
          • 2015-02-28
          • 2017-06-23
          • 2020-09-02
          • 1970-01-01
          • 2014-06-10
          • 1970-01-01
          • 2016-09-17
          • 2015-02-05
          • 2019-02-26
          相关资源
          最近更新 更多