初学者 Haskell 问题:如何在 Haskell 中查找索引(手动使用递归而不使用 findIndices)

Beginner Haskell question: how do I find indices in Haskell (manually using recursion without using findIndices)

我有一个 Haskell 作业练习,使用递归手动重新创建 findIndices

我通过在每次找到符合条件的索引时硬编码 cons 0 来简化问题:

positions :: (a -> Bool) -> [a] ->[Integer] 
positions p [] = []
positions p (x:xs) 
| p x = 0 : positions p xs
    | otherwise = positions p xs

但是我希望它输出索引,而不是在输出列表的每个位置输出 0,但我不知道如何使用计数变量来做到这一点。

我试图通过将索引输出到每个项目来简化它,但也无法解决这个问题,所以我得到了:

pos :: [a] -> [Integer]
pos [] = []
pos (x:xs) = 0 : pos xs

列表中的每个项目 returns 都是 0 所以 [2,3,4,5] returns [0,0,0,0] 正如预期的那样,但我可以'不知道怎么做 return [0,1,2,3]

我可以让它计算列表中有多少项,但我不知道如何将计数变量放入列表中。

pos1 :: [a] -> Integer 
pos1 [] = 0
pos1 (x:xs) = let count = pos1 xs in count+1

如能在“Haskell for Dummies”语言中提供任何帮助,我们将不胜感激。

有几种方法可以做到这一点。我将重点介绍一种基本方法,即使存在利用库列表函数的更好方法。

你写道你想要一个计数器变量。因此,首先定义一个将计数器(下面的变量 index)作为附加参数的函数。按照您发布的代码,我们得到:

positionsIndex :: Integer -> (a -> Bool) -> [a] -> [Integer] 
positionsIndex index p []     = ...
positionsIndex index p (x:xs) = ...

之后,我们可以通过提供额外的参数来定义想要的函数

positions :: (a -> Bool) -> [a] -> [Integer] 
positions p xs = positionsIndex 0 p xs

上面的0将计数器参数初始化到第一个位置。

现在,您应该通过适当调整您已经发布的代码来完成 positionsIndex。请注意,您必须将计数器传递给对 positionsIndex.

的每个递归调用

您可以使 positionsIndex 适应以下内容的局部函数。注意使所有相关方程完美对齐。

positions :: (a -> Bool) -> [a] -> [Integer] 
positions p xs = ...
   where
   positionsIndex :: Integer -> (a -> Bool) -> [a] -> [Integer] 
   positionsIndex index p []     = ...
   positionsIndex index p (x:xs) = ...