0

I have a function that has parameters

whatIndex ::  (Eq a) => a -> [a] -> Integer

where I return the index of a inside [a], starting at 0, or return -1 if it's not found. This is what I wrote

module WhatIndex where

whatIndex ::  (Eq a) => a -> [a] -> Integer

whatIndex p [] = -1

whatIndex p (a:as) 
    | p==a = index
    | otherwise = whatIndex p as
    where index = 1+whatIndex p as

Obviously, I'm not correctly increasing index here. Any idea why this isn't working? Also, I cannot change parameters.

========================

Here is some basic input/output

whatIndex 3 [] = -1
whatIndex 2 [1,2,3,2,1]=1
whatIndex 1 [1,2,3,2,1]=0
whatIndex 'b' ['a' .. 'z']=1
4
  • What should this be doing? Could you provide a test case or 2? Commented Feb 13, 2013 at 2:16
  • its a standard .index() function on an array I believe. I believe he's expecting this to return the index of the element within the list e.g.: whatIndex 17 [1,2,3,4,5,15,16,17,19] = 7 Commented Feb 13, 2013 at 2:19
  • Yes, basically I am making an index function. I can't seem to get the logic figured out as to how to increment index. Commented Feb 13, 2013 at 2:26
  • BTW, what you really want here is a function that returns Maybe Int, because you want to make it clear in the type that the function is partial. Such a function, elemIndex, already exists in Data.List--you can take a look at the source here. Commented Feb 13, 2013 at 4:24

2 Answers 2

4

1+whatIndex p as will go through all of the remaining list and count them, it won't give you the index. Just use an iterative recursive helper function like this...

You can use either a local function, or the lifted version, which is what I have here.

whatIndex' ::  (Eq a) => Integer -> a -> [a] -> Integer

whatIndex' _ _ [] = -1

whatIndex' i p (x:xs) 
    | p == x = i
    | otherwise = whatIndex' (i+1) p xs

whatIndex p xs = whatIndex' 0 p xs

main = print $ whatIndex 'a' "bbbbaccc"

Here's a non tail-recursive version:

whatIndex p (x:xs)
    | p == x = 0
    | otherwise = 1 + whatIndex p xs

Tail recursion refers to a class of recursive functions where the "last" or "final" function call in a recursive function is to the function itself. So that means that the function is not calling some other function (like +) in the "tail position" (the last place where a function call takes place). You can clearly see that the final function that is called in the first version of whatIndex is whatIndex whereas the final function that is called in the second version (with a call to whatIndex as a parameter) is +.

http://en.wikipedia.org/wiki/Tail_call

Edit: here's a version that corresponds more closely with your specification, although it's a bit convoluted and inefficient.

whatIndex p xs 
    | not (any (==p) xs) = -1
    | otherwise = whatIndex' p xs where
        whatIndex' p (x:xs)
            | p == x = 0
            | otherwise = 1 + whatIndex' p xs
Sign up to request clarification or add additional context in comments.

8 Comments

I cannot change the parameters.
This isn't changing any parameters of whatIndex, it's the exact same as Pubby's answer, except the local function has been lifted to the top level scope.
Also your question said "tail recursion" which implies some kind of accumulator parameter. If you wanted a non tail-recursive version you should've specified that.
No I definitely want a tail recursion answer. I'm a noobie at tail recursion so I may not be completely understanding of what's going on in this code. However, you have whatIndex' :: (Eq a) => Integer -> a -> [a] -> Integer where my restrictions don't have an Integer.
No, you want a non tail-recursive one. I'll add that though.
|
2

Try using an accumulator parameter if you want tail recursion:

whatIndex :: (Eq a) => a -> [a] -> Integer
whatIndex =
  let whatIndex' count p [] = -1
      whatIndex' count p (a:as)
        | p==a = count
        | otherwise = whatIndex' (count + 1) p as
  in whatIndex' 0

5 Comments

Your method has more parameters than allowed. I don't have Integer -> a -> [a], just a -> [a]
@Soulzityr No it doesn't. That's only for the local function.
I'm using the Eclipse plug-in, writing a module so I won't and shouldn't be using let or in keywords. Does that change how to do this?
@Soulzityr I don't understand those requirements, but use Wes's answer then. It is doing the same thing, but the whatIndex' function is at global scope instead of local.
Ah, I understand now. My requirements are convoluted. I need to sort out why what I thought was tail recursion, in fact, isn't. My knowledge was based on popular online tutorials too...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.