使用数组解析haskell中的方案向量

时间:2021-03-21 17:02:21

I'm attempting the Write Yourself a Scheme in 48 Hours tutorial and as someone new to haskell it's pretty difficult. I'm currently working on a problem where I'm supposed to add the ability to parse scheme vectors (section 3.4 exercise 2).

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

I'm using this data type:

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

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

To parse, I'm looking for '#(' then trying to parse the vector contents, drop them in a list and convert that list to an array.

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

I'm trying to use a list parsing function that I already have and am using but it parses scheme lists into the LispVal List above and I'm having a hard time getting that back into a regular list. Or at least that's what I think my problem is.

我正在尝试使用我已经拥有并正在使用的列表解析函数,但它将方案列表解析为上面的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

and here's the list parser:

这是列表解析器:

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

Any ideas on how to fix this? Thanks, Simon

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

-edit- Here's the compilation error I get:

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

Couldn't match expected type a -> LispVal' against inferred typeParser LispVal' In the second argument of (.)' namelyparseList' In the second argument of (.)' namely lispValToList . parseList' In the expression: listToArray . lispValToList . parseList

无法匹配预期类型a - > LispVal'与推断的typeParser LispVal'在(。)'ieparseList'的第二个参数中,在(。)'的第二个参数中,即lispValToList。 parseList'在表达式中:listToArray。 lispValToList。 parseList

2 个解决方案

#1


6  

You do not provide lispValtoList but I suppose that it have the following type

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

lispValtoList :: LispVal -> [LispVal]

This would suggest the compiler to think that parseList is of type a -> LispVal. But it is not since it is Parser LispVal and so something like P String -> [(LispVal,String)].

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

You have to extract the LispVal value that was parsed before putting it in a list. So parseVectorInternals must probably look like

在将它放入列表之前,您必须提取已解析的LispVal值。所以parseVectorInternals看起来应该是这样的

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

You could write something more compact, but this code tries to be self-documented ;)

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

#2


2  

parseList is a Monad of type parser LispVal whereas lispValtoList wants a plain LispVal so:

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

parseVectorInternals = listToArray . lispValtoList `liftM` parseList

If you are where I was 8 weeks ago reading the same book the following will help you as well:

如果你是我8周前读到同一本书的地方,以下内容对你有帮助:

All these lines are equivalent:

所有这些都是等价的:

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)

#1


6  

You do not provide lispValtoList but I suppose that it have the following type

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

lispValtoList :: LispVal -> [LispVal]

This would suggest the compiler to think that parseList is of type a -> LispVal. But it is not since it is Parser LispVal and so something like P String -> [(LispVal,String)].

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

You have to extract the LispVal value that was parsed before putting it in a list. So parseVectorInternals must probably look like

在将它放入列表之前,您必须提取已解析的LispVal值。所以parseVectorInternals看起来应该是这样的

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

You could write something more compact, but this code tries to be self-documented ;)

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

#2


2  

parseList is a Monad of type parser LispVal whereas lispValtoList wants a plain LispVal so:

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

parseVectorInternals = listToArray . lispValtoList `liftM` parseList

If you are where I was 8 weeks ago reading the same book the following will help you as well:

如果你是我8周前读到同一本书的地方,以下内容对你有帮助:

All these lines are equivalent:

所有这些都是等价的:

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)