问题
type Dictionary = [(String, String)]
dict :: Dictionary
dict = ("Deutsch", "English"):[]
insert :: Dictionary -> (String,String) -> Dictionary
insert dict entry = dict ++ [entry]
One thing that I didn't find about the way lists work: Is it somehow possible to overwrite the existing dict with the entry added in insert? Or is it necessary to, in the next step, always write out the list that was put out by insert?
insert [("German", "English"), ("Hallo", "hello")] ("Versuch", "try")
So far, this is the only way I have been able to add something to the new list without losing the previous entry. However, next on the list of things to implement is a search command, so I wonder if I'd also have to write this out in the search function.
回答1:
The idea of functional programming is in general that your data is immutable. This means once you have created a list, you can NEVER change that list. But you can copy that list, make modifications to it, and keep that as well.
So when you have a list like so
test = [1,2,3]
We can modify this by adding 4
to the start:
test2 = 4 : test
:
called the cons operator, puts an element in front of a list. Do note that x:xs
(the same as doing [x]++xs
) has a better performance than doing xs++[x]
So now we have two bindings, one of test
to [1,2,3]
and one of test2
to [4,1,2,3]
Hope this clarifies things
To give a full example:
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")
If you're new to functional programming, I would recommend reading Learn You a Haskell for Great Good , which is a fantastic (and free) book on how to use Haskell -- and functional programming in general.
回答2:
It's not too tough to do this
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")]
If you can't use Data.List
then you can define lookup
by
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
Now if you load up 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")]
回答3:
If you want to replace an existing pair with the same key then you could write insert as:
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)
However if you are writing an association list, then you can simplify it by inserting new items at the front of the list:
insert :: Dictionary -> (String, String) -> Dictionary
insert = flip (:)
if you then search from the front of the list, it will find any values added more recently first.
回答4:
In Haskell, most values are immutable, meaning that you can not change their value. This seems like a huge constraint at first, but in reality it makes it easier to reason about your program, especially when using multiple threads.
What you can do instead is continually call insert
on the dictionary returned when you call insert
, for example:
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
回答5:
One simply can't 'overwrite' anything in a pure language (outside of ST monad). If I understood your question correctly, you are looking for something like this:
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
来源:https://stackoverflow.com/questions/20567255/functionality-of-adding-to-lists-in-haskell-overwriting-an-existing-list