簡體   English   中英

如何在不進入無限循環的情況下修改Haskell列表?

[英]How do I modify a Haskell list without entering an infinite loop?

我正在Haskell中編寫一段代碼,我有一行代碼如下:

addElement :: [a] -> a -> [a]
addElement list elem = list ++ [elem]

我需要(或者至少我認為)這樣的函數,以便在我正在實現的圖形數據結構的頂點列表中添加新頂點。 現在,我可以按如下方式調用此函數

newlist = addElement oldlist elem

一切都很好。 但是,如果我寫的話

mylist = addElement mylist elem

然后在調用終止后嘗試用mylist做任何事情(確實如此),我進入一個無限循環,如果我理解正確,這是由於對Haskell的懶惰評估或某種類型( mylist擴展為addElement (addElement ... elem) elem如果我做對了嗎?)。

這對我的特定實現當然是不好的,因為為了我的目的,我現在每次需要向列表添加元素時都必須創建新列表。 那么如何使元素添加功能按我想要的方式工作呢?

首先, mylist = addElement mylist elem是一個等式,它不是賦值 不會被評估一次:因為Haskell是一種聲明性語言,所以你不能改變一個變量 :一旦給它一個值,它就會總是有這個值。

因此,您的等式將導致:

mylist = addElement mylist elem
       = addElement (addElement mylist elem) elem
       = addElement (... (addElement mylist elem) ...) elem

你明白了。

不過, 每次都不需要構建一個完整的新列表 :你可以簡單地使用(h:t) 追加到頭部

addElement :: [a] -> a -> [a]
addElement t h = (h:t)

這將在O(1)中構造一個“新”列表,它將舊列表重用為尾部。 如前所述,元素將被添加到前面。

解決該問題的另一種方法是使用差異列表 這里的列表表示為:

type DiffList a = a -> [a]

一個空列表是:

emptyDiffList :: DiffList a
emptyDiffList = \x -> x

在這種情況下,你與差異列表:

groundDiffList :: DiffList a -> [a]
groundDiffList x = x []

並且您可以使用以下命令將元素添加到列表末尾

addElement :: DiffList a -> a -> DiffList a
addElement l el = \x -> l (el:x)

然而,你總是需要為“新列表” 創建一個新變量 :你不能一下子給mylist另一個值(你當然可以使用遞歸,但在那種情況下,那些技術上是兩個不同的變量: 調用者mylist ,以及被調用者mylist )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM