5

我正在尝试在 48 小时内编写自己的计划教程,作为一个新的 haskell 人,这非常困难。我目前正在解决一个问题,我应该添加解析方案向量的能力(第 3.4 节练习 2)。

我正在使用这种数据类型:

data LispVal = Atom String                  
         | List [LispVal]                   
         | Vector (Array Int LispVal)

要解析,我正在寻找 '#(' 然后尝试解析向量内容,将它们放入列表中并将该列表转换为数组。

我正在尝试使用我已经拥有并正在使用的列表解析功能,但它将方案列表解析到上面的 LispVal 列表中,我很难将其恢复到常规列表中。或者至少这就是我认为我的问题所在。

lispValtoList :: LispVal -> [LispVal]
lispValtoList (List [a]) = [a]

parseVector :: Parser LispVal
parseVector = do string "#("
             vecArray <- parseVectorInternals       
             char ')'
             return $ Vector vecArray

parseVectorInternals :: Parser (Array Int LispVal)
parseVectorInternals = listToArray . lispValtoList . parseList  

listToArray :: [a] -> Array Int a
listToArray xs = listArray (0,l-1) xs
    where l = length xs

这是列表解析器:

parseList :: Parser LispVal
parseList = liftM List $ sepBy parseExpr spaces

有想法该怎么解决这个吗?谢谢,西蒙

-edit- 这是我得到的编译错误:

无法匹配预期类型a -> LispVal' against inferred typeParser LispVal' 在 parseList 的第二个参数中 (.)' namely' 在 lispValToList 的第二个参数中(.)' namely 。parseList' 在表达式中: listToArray 。lispValToList 。解析列表

4

2 回答 2

6

您不提供lispValtoList,但我认为它具有以下类型

lispValtoList :: LispVal -> [LispVal]

这将建议编译器认为它parseList是 type a -> LispVal。但它不是,因为它是Parser LispVal这样的P String -> [(LispVal,String)]

您必须先提取LispVal已解析的值,然后再将其放入列表中。所以parseVectorInternals可能看起来像

parseVectorInternals = do parsedList <- parseList 
                          let listOfLispVal = lispValtoList parsedList
                          return $ listToArray listOfLispVal

你可以写一些更紧凑的东西,但是这段代码试图自我记录;)

于 2011-06-23T19:12:04.813 回答
2

parseList是 Monad 类型parser LispVal,而 lispValtoList 想要一个普通的 LispVal 所以:

parseVectorInternals = listToArray . lispValtoList `liftM` parseList

如果您在 8 周前阅读同一本书的地方,那么以下内容也会对您有所帮助:

所有这些行都是等效的:

parseVectorInternals = (listToArray . lispValtoList) `liftM` parseList
parseVectorInternals = liftM (listToArray . lispValtoList) parseList
parseVectorInternals = parseList >>= \listLispVal -> return listToArray (lispValtoList listLispVal)
parseVectorInternals = do 
  listLispVal <- parseList 
  return listToArray (lispValtoList listLispVal)
于 2011-06-24T05:55:39.070 回答