Reputation:
I'm trying to store data in a key-value style in Haskell. The idea is that I have an identification (Ident) and it can be a single value or a list of them.
I have tried the following structure:
type Ident = String
data SymTable a = ST [(Ident, Either a [a])]
deriving (Show)
The problem comes when I try to define the following basic functions to store/retrieve data from the data structure:
setVar :: SymTable a -> Ident -> Either a [a] -> SymTable a
getVar :: SymTable a -> Ident -> Either a [a]
I've tried several implementations but I can't get the compiler to work (accept types).
As a constraint, I can't use any external library (no Map or similars).
UPDATE
So my idea was to do something like this:
setVar :: SymTable a -> Ident -> Either a [a] -> SymTable a
setVar (ST xs) i a = ST ([(i, a)] ++ xs)
getVar :: SymTable a -> Ident -> Either a [a]
getVar t i = snd (head (filter (\x -> fst x == i) t))
UPDATE 2
Following @freestyle answer, i changed a little bit setVar so if you input an Ident that already exists, it overwrites it.
setVar :: SymTable a -> Ident -> Either a [a] -> SymTable a
setVar (ST xs) i a = ST ([(i, a)] ++ clearList xs i)
where
clearList [] _ = []
clearList (x:xs) i
| fst x == i = clearList xs i
| otherwise = x : clearList xs i
getVar stays as he suggested:
getVar :: SymTable a -> Ident -> Maybe (Either a [a])
getVar (ST xs) i = lookup i xs
Upvotes: 1
Views: 2124
Reputation: 3790
I don't see any problem with compilation of setVar
, but more better is setVar (ST xs) i a = ST ((i, a) : xs)
.
You have problem with getVar
. The filter
can "eat" a list, but you gave the SymTable
.
So you can do like this:
getVar (ST xs) i = snd (head (filter (\x -> fst x == i) xs))
More better way:
getVar (ST xs) i = fromJust (lookup i xs)
But, if key doesn't exist you will get an exception. So, maybe you want like this:
getVar :: SymTable a -> Ident -> Maybe (Either a [a])
getVar (ST xs) i = lookup i xs
Upvotes: 3