2012-12-15 84 views
0

我正在尝试编写一个函数来检索列表中的第n个元素。使用Haskell在列表中查找第n个元素

这是我到目前为止有:

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

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

这是错误我得到:

Error occurred 
ERROR line 2 - Cannot justify constraints in explicitly typed binding 
*** Expression : main 
*** Type   : IO() 
*** Given context :() 
*** Constraints : (Show a, Num [a]) 
+4

试着写了'nth'类型注释(这是一个很好的做法反正)。这应该使问题更加明显。 –

+1

为什么你不使用xs! n? –

+2

既然你希望'nnth'返回列表的一个*元素*,你一定希望它具有类型'Int - > [a] - > a',对吧?那么,你的第一个定义是'nnth_ [] = []',它是一个* list *(或者“返回一个列表”,如果你愿意的话),所以它定义了一个类型为'Int-> [a] - > [a]'。那么,什么*应该*'nth'做一个空列表?这是个好问题!一种方法是简单地让它失败,另一种方法是给它返回类型'Maybe a',如果列表太短,则返回'Nothing'。 – gspr

回答

5

为什么Num [a]约束?因为在[]子句中,函数返回一个列表[],而在另一个子句中,它返回一个列表元素x。这意味着它仅限于其元素是列表本身的列表。但是你可以用[1,2,10]的名单来称呼它。所以Haskell看到一个数字文字1,并且想要将它解释为一个也是数字的列表。它还需要它是Showprint实例才能够表现出来:

Prelude> :i print 
print :: (Show a) => a -> IO()   -- Defined in System.IO 
+0

这就是为什么写明确的函数签名是有帮助的,所以你可以看到你明显地试图返回一个不同于你声明的类型。 – alxp

+1

@alxp它通常也不会写任何类型的签名,特别是对于新手来说,但是 - 在加载定义之后,检查*推断*签名:'Prelude> let {nth _ [] = []; nth a(x:xs)= x} - Prelude>:i nth - nth :: t - > [[a]] - > [a]'。 –

0

这里,我们去:

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

您在条款

nth _ [] = [] 

返回列表和子句中的列表元素

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

所以你的函数的类型是

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

你可以检查了这一点。您的功能不能用于任何列表返回任何指数的元素,所以你必须使用也许返回“元素未找到”

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 
相关问题