我正在尝试编写remove
函数,以便用户可以输入remove 'd' ["abc", "dc", "ad"]
并获取输出["abc", "c", "a"]
。
我的代码是:
remove :: Eq a => a -> [[a]] -> [[a]]
remove a (x:xs) = filter (not.a) (x:xs)
但是我收到以下错误消息:
Occurs check: cannot construct the infinite type: a = [a] -> Bool
When generalising the type(s) for `remove'
错误消息的含义是什么,以及如何更改第二行以使其有效?
答案 0 :(得分:6)
filter
的类型是
filter :: (a -> Bool) -> [a] -> [a]
所以传递给filter
的第一个参数必须是从列表的元素类型到Bool
的函数。在
remove :: Eq a => a -> [[a]] -> [[a]]
remove a (x:xs) = filter (not.a) (x:xs)
你说
a
的类型为a
,列表的类型为[[a]]
,即列表元素类型为[a]
,not . a
是filter
的第一个参数,类型为[a] -> Bool
。这些暗示着
a = [a] -> Bool
但这是一种无限型。
如果filter (not . (a `elem`))
适用于外部列表,则可能表示类似filter (a `notElem`)
或等效filter
的内容,如果要删除,则map (filter (/= a))
来自每个包含列表的元素。
答案 1 :(得分:5)
您声明参数a
是支持相等的任何类型。
但是你在布尔表达式中使用它:not . a
。
not
的类型为:: Bool -> Bool
,因此a
必须为Bool
类型。但是你已经说不了,它的类型为Eq t => t
。
这是一个类型错误。
我认为您的意思是过滤所有不等于a
的元素,即:
remove a xs = filter (/= a) xs
但是,您的输入也是嵌套列表,因此您必须将过滤器映射到内部元素上:
remove a xs = map (filter (/= a)) xs