在Haskell中添加列表/覆盖现有List的功能

时间:2013-12-13 13:04:14

标签: list haskell overwrite addition

type Dictionary = [(String, String)]

dict :: Dictionary
dict = ("Deutsch", "English"):[]

insert :: Dictionary -> (String,String) -> Dictionary
insert dict entry = dict ++ [entry]

我没有找到关于列表工作方式的一件事:是否有可能用insert中添加的条目覆盖现有的dict?或者,在下一步中,是否有必要写出插入列出的列表?

insert [("German", "English"), ("Hallo", "hello")] ("Versuch", "try")

到目前为止,这是我能够在不丢失之前条目的情况下向新列表添加内容的唯一方法。但是,接下来要实现的东西就是搜索命令,所以我想知道我是否还必须在搜索功能中写出来。

5 个答案:

答案 0 :(得分:2)

函数式编程的概念通常是您的数据是不可变的。这意味着一旦创建了列表,就不能更改该列表。但是你可以复制该列表,对其进行修改,并保留它。

所以当你有一个像这样的列表时

test = [1,2,3]

我们可以通过在开头添加4来修改此内容:

test2 = 4 : test

:调用cons运算符,将一个元素放在列表前面。请注意x:xs(与执行[x]++xs相同)的效果优于执行xs++[x]

现在我们有两个绑定,一个是test[1,2,3],另一个是test2[4,1,2,3]

希望这能澄清事情


举一个完整的例子:

type Dictionary = [(String, String)]

insert :: Dictionary -> (String,String) -> Dictionary
insert dict entry = dict ++ [entry]

dict0 = [ ("Deutsch", "English") ]
dict1 = insert dict0 ("Hallo", "hello")
dict2 = insert dict1 ("Versuch", "try")

如果您不熟悉函数式编程,我建议您阅读Learn You a Haskell for Great Good,这是一本关于如何使用Haskell的精彩(免费)书籍,以及一般的函数式编程。

答案 1 :(得分:1)

这样做并不太难

import Data.List (lookup)

insert :: Eq a => (a,b) -> [(a,b)] -> [(a,b)]
insert (a,b)  []           = [(a,b)]
insert (a,b) ((c,d):rest) = if a == c
    then (a,b) : rest
    else (c,d) : insert (a,b) rest

---

dict :: [(String, String)]
dict = [("Deutsch", "English")]

如果您无法使用Data.List,则可以通过

定义lookup
lookup :: Eq a => a -> [(a,b)] -> Maybe b
lookup _  []          = Nothing
lookup k ((a,b):rest) = if k == a then Just b else lookup k rest

现在如果加载GHCI:

>> let dict' = insert ("Ein","One") dict
>> dict'
[("Deutsch","English"),("Ein","One")]
>> lookup "Ein" dict'
Just "One"
>> insert ("Deutsch", "Francais") dict'
[("Deutsch","Francais"),("Ein","One")]

答案 2 :(得分:0)

如果要使用相同的键替换现有的对,则可以将insert写为:

insert :: Dictionary -> (String, String) -> Dictionary
insert [] p = [p]
insert ((dk, dv):ps) p@(k, v) | dk == k = p:ps
insert (p:ps) ip = p : (insert ps ip)

但是,如果您正在编写关联列表,则可以通过在列表前面插入新项来简化它:

insert :: Dictionary -> (String, String) -> Dictionary
insert = flip (:)

如果您从列表的前面搜索,它将首先找到最近添加的任何值。

答案 3 :(得分:0)

在Haskell中,大多数值都是 immutable ,这意味着您无法更改其值。这看起来似乎是一个巨大的约束,但实际上它可以更容易推理您的程序,尤其是在使用多个线程时。

您可以执行的操作是在致电insert时在字典上不断调用insert,例如:

mainLoop :: Dictionary -> IO ()
mainLoop dict = do
    putStrLn "Enter the German word:"
    german <- getLine
    putStrLn "Enter the English word:
    english <- getLine
    let newDict = insert dict (german, english)
    putStrLn "Continue? (y/n)"
    yesno <- getChar
    if yesno == 'y'
        then mainLoop newDict
        else print newDict

main = do

答案 4 :(得分:0)

一个人根本无法用纯语言“覆盖”任何东西(在ST monad之外)。如果我理解你的问题,你正在寻找这样的东西:

insert :: Dictionary -> (String,String) -> Dictionary
insert [] b = [b]  -- If this point is reached where wasn't matching key in dictionary, so we just insert a new pair
insert (h@(k, v) : t) b@(k', v')
    | k == k'   = (k, v') : t      -- We found a matching pair, so we 'update' its value
    | otherwise = h : insert t b