我正在尝试在Haskell中以键值方式存储数据。我的想法是我有一个标识(Ident),它可以是单个值或它们的列表。
我尝试了以下结构:
type Ident = String
data SymTable a = ST [(Ident, Either a [a])]
deriving (Show)
当我尝试定义以下基本功能来存储/检索数据结构中的数据时,问题出现了:
setVar :: SymTable a -> Ident -> Either a [a] -> SymTable a
getVar :: SymTable a -> Ident -> Either a [a]
我已经尝试了几种实现,但是我无法让编译器工作(接受类型)。
作为约束,我不能使用任何外部库(没有地图或类似物)。
更新
所以我的想法是做这样的事情:
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))
更新2
在@freestyle回答之后,我改变了一点setVar,所以如果你输入一个已经存在的Ident,它会覆盖它。
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保持按照他的建议:
getVar :: SymTable a -> Ident -> Maybe (Either a [a])
getVar (ST xs) i = lookup i xs
答案 0 :(得分:3)
我没有看到编译setVar
时遇到任何问题,但更好的是setVar (ST xs) i a = ST ((i, a) : xs)
。
getVar
有问题。 filter
可以"吃"列表,但您提供了SymTable
。
所以你可以这样做:
getVar (ST xs) i = snd (head (filter (\x -> fst x == i) xs))
更好的方式:
getVar (ST xs) i = fromJust (lookup i xs)
但是,如果密钥不存在,您将获得异常。所以,也许你想这样:
getVar :: SymTable a -> Ident -> Maybe (Either a [a])
getVar (ST xs) i = lookup i xs