我正在尝试“在48小时内编写自己的计划”教程,而作为一个新手,这非常困难。
我目前正在研究一个应该添加解析方案 vector 的功能的问题(第3.4节练习2)。

我正在使用此数据类型:

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

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

我正在尝试使用已经拥有并且正在使用的列表解析功能,但是它会将方案列表解析到上面的LispVal List中,并且很难将其返回到常规列表中。至少我认为这就是我的问题。
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

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

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

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

最佳答案

您没有提供lispValtoList,但我想它具有以下类型

lispValtoList :: LispVal -> [LispVal]

这将建议编译器认为parseLista -> LispVal类型。但这不是因为它是Parser LispVal,而是P String -> [(LispVal,String)]之类的东西。

您必须先提取已解析的LispVal值,然后才能将其放入列表中。
所以parseVectorInternals可能看起来像
parseVectorInternals = do parsedList <- parseList
                          let listOfLispVal = lispValtoList parsedList
                          return $ listToArray listOfLispVal

您可以写一些更紧凑的东西,但是这段代码会尝试自我记录下来;)

07-26 04:30