theWhiteKnight
theWhiteKnight

Reputation: 61

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

I have a Haskell homework exercise to manually re-create findIndices using recursion.

I've simplified the problem by hard-coding a cons 0 each time it finds an index that meets the criteria:

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

But instead of outputting a 0 in each position of the output list, I want it to output the index but I cannot work out how to do this using a count variable.

I've tried to simplify this by just outputting the index to every item but can't work this out either so I've got:

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

which returns a 0 for every item in the list so [2,3,4,5] returns [0,0,0,0] as expected but I can't work out how to make it return [0,1,2,3]

I can make it count how many items are in the list but I can't work out how to put the count variable into the list.

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

Any help in "Haskell for Dummies" language would be much appreciated.

Upvotes: 2

Views: 163

Answers (1)

chi
chi

Reputation: 116174

There are several ways to do that. I'll focus on a basic approach, even if better ones exist which exploit the library list functions.

You wrote you want a counter variable. So, start by defining a function which takes that counter (variable index below) as an additional argument. Following the code you posted, we get:

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

After that, we can define the wanted function by providing the additional argument

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

The 0 above initializes the counter argument to the first position.

Now, you should finish positionsIndex, by suitably adapting your already posted code. Note that you will have to pass the counter to each recursive call to positionsIndex.


You can make positionsIndex a local function adapting the following. Be careful to make all the related equations perfectly aligned.

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

Upvotes: 1

Related Questions