作为初学者,我正在研究Haskell 99问题的第3项。第一个代码片段是我的解决方案。但是,我无法添加[a] -> Int -> a
的类型声明。
它产生错误:Couldn't match type 'a' with 'Int'
--My Solution
--elementAt :: [a] -> Int -> a
elementAt xs num = head . reverse $ takeWhile (<num+1) xs
同时,问题3中的一个解决方案与相同的输出完美配合。
elementAt' :: [a] -> Int -> a
elementAt' list i = list !! (i - 1)
我在没有声明的情况下使用GHCI中的:type
作为elementAt
并显示:
elementAt :: (Num c, Ord c) => [c] -> c -> c
这两个功能有什么区别?
答案 0 :(得分:3)
takeWhile (<num+1) xs
表示您希望在列表xs
前面加上元素,而元素(不是索引!)小于num + 1
。由于您将num
(这是一个Int)与列表元素进行比较,编译器会推断列表元素也必须是Int
,这与您的类型声明相矛盾。
如果没有类型声明,GHC会推断xs
的元素和num
必须是相同的类型(因为您将列表元素与num进行比较)。此类型必须具有Ord
实例(用于比较)以及Num
实例(因为添加)。
答案 1 :(得分:1)
takeWhile (< num + 1)
的类型为[Int] -> [Int]
。
但xs
的类型为[a]
。
基本上,您尝试将谓词Int -> Bool
应用于a
类型的元素。
如果要根据列表中的位置进行过滤,首先需要使用每个元素的位置来扩充输入列表。您可以使用zip
:
zip xs [1..]
然后,您可以根据结果列表的第二个元素的值删除元素。