0

I am trying to write a function that retrieves the nth element in a list.

Here's what I have so far:

main :: IO ()
main = do print (nth 3 [1,2,10])

nth _ [] = [] 
nth a (x:xs) 
 | (a == 1) = x 
 | otherwise = nth (a-1) xs

This is the error I get:

Error occurred
ERROR line 2 - Cannot justify constraints in explicitly typed binding
*** Expression    : main
*** Type          : IO ()
*** Given context : ()
*** Constraints   : (Show a, Num [a])
7
  • 4
    Try writing a type annotation for nth (this is a good practice anyway). That should make the problem here more apparent. Commented Dec 15, 2012 at 17:50
  • 1
    Why don't you just use xs !! n ? Commented Dec 15, 2012 at 17:50
  • 2
    Since you want nth to return an element of the list, you surely want it to have type Int -> [a] -> a, right? Well, your first definition, nth _ [] = [], is a list (or "returns a list", if you prefer), so it's a definition of a function of type Int -> [a] -> [a]. So what should nth do with an empty list? That's a good question! One way is to simply have it fail, another is to give it return type Maybe a, with Nothing returned in case the list is too short. Commented Dec 15, 2012 at 17:55
  • But what doe sthe error message say? Any ideas? Commented Dec 15, 2012 at 18:01
  • 3
    The error message is not helpful here. That happens quite often in Haskell, when you fail to give enough type annotations. Since you haven't told it what the type of nth is supposed to be, the compiler figures out some amazing (and often rather ridiculous) signature and only notices a the call site (here, main) that it's bogus. That's why you get an error message demandig Num [a], which is obviously weird and one of the typical signs that you've made an error somewhere else and didn't build a safety-net in form of an explicit type signature there. Commented Dec 15, 2012 at 18:07

3 Answers 3

5

Why Num [a] constraint? Because in the [] clause you have your function returning a list, [], and in the other clause you have it return a list's element, x. Which means that it is only defined for lists whose elements are lists themselves. But you call it with a list of [1,2,10]. So Haskell sees a numeric literal 1 and wants to interpret it as a list that is also a number. It also needs it to be an instance of Show for print to be able to show it:

Prelude> :i print
print :: (Show a) => a -> IO ()         -- Defined in System.IO
Sign up to request clarification or add additional context in comments.

2 Comments

This is why it's helpful to write explicit function signatures, so you can see that you're obviously trying to return a different type than what you've declared.
@alxp it is also oftentimes helpful to not write any type signature at all, especially for a newbie, BUT - after loading the definition, to inspect the inferred signature: Prelude> let {nth _ [] = [];nth a (x:xs) = x} -- Prelude> :i nth -- nth :: t -> [[a]] -> [a].
2

You are returning list in clause

nth _ [] = []

and a list element in clause

nth a (x:xs) 
  | (a == 1) = x 
  | otherwise = nth (a-1) xs

so the type of your function is

*Main> :t nth
nth :: (Eq a1, Num a1) => a1 -> [[a]] -> [a]

you can check this out. Your function can not return element of any index for any list, so you must use Maybe to return "element not found"

nth _ [] = Nothing
nth a (x:xs) 
 | (a == 1) = Just x 
 | otherwise = nth (a-1) xs


*Main> :t nth
nth :: (Eq a1, Num a1) => a1 -> [a] -> Maybe a

Comments

0

Here we go:

nth a (x:xs) 
| (a == 1) = x 
| otherwise = nth (a-1) xs

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.