0

我们被要求编写一个函数来查看应用过滤器函数的结果是否为空列表。我尝试了以下方法,但它给了我提到的错误。

isListEmpty ::((a -> Bool) -> [a] -> [a]) -> Bool
isListEmpty f       | length f == 0 = True
                    | otherwise = False

错误:

...- Type error in application
*** Expression     : length f
*** Term           : f
*** Type           : (b -> Bool) -> [b] -> [b]
*** Does not match : [a]

这个想法是练习高阶函数。知道如何解决这个问题吗?

4

4 回答 4

3
isListEmpty ::((a -> Bool) -> [a] -> [a]) -> Bool
isListEmpty f       | length f == 0 = True
                    | otherwise = False

你的函数的第一个参数isListEmpty是一个你给它的名字f和它的类型的函数,(a -> Bool) -> [a] -> [a].f输入length这个函数失败了,因为这个函数length接受带有签名的[a]类型并产生一个 type Int

您可以通过转到 ghci 并键入:t lengthwhich来查看这一点[a] -> Int

如果您首先将 f 应用于具有类型的列表,[a]那么您可以使用lengthand==0检查它是否为空。然而,该函数null是测试列表是否为空的惯用方法,因此我建议改用它。

编辑添加如何编写类似函数的示例。

假设我想在执行另一个函数(如 drop 或 init 等)之后找到列表的长度。首先只需完整地编写包含所有参数的函数:

manipulateList :: ([a] -> [a]) -> [a] -> Int
manipulateList fn lst = length (fn lst)

而不是length (fn lst)我们可以用函数组合重写它(length.fn) lst

manipulateList :: ([a] -> [a]) -> [a] -> Int
manipulateList fn lst = (length.fn) lst

现在您可以像使用代数方程一样取消lst两边。

manipulateList :: ([a] -> [a]) -> Int
manipulateList fn = (length.fn)

现在我们有一个高阶函数,它接受一个函数fn并在fn应用于它之后找到列表的长度。

于 2013-01-27T01:44:05.743 回答
3

好像你有错误的类型注释。考虑以下解决方案:

isListEmpty :: (a -> Bool)        -- filtering function
            -> [a]                -- given list
            -> Bool               -- the result
isListEmpty f = null . filter f

一些例子:

> isListEmpty odd [2, 4]
True
> isListEmpty odd [1, 2, 4]
False
> 

使用length不是最好的主意,因为您必须遍历整个列表来进行检查,并且列表甚至可以是无限的。null可以处理这种情况:

> isListEmpty even [1..]
False
> 

编辑 1

我们的问题要求我们使用内置的过滤器函数作为参数

不太明白它的含义,但您可能想要这样做:

isListEmpty :: ([a] -> [a]) -> [a] -> Bool
isListEmpty = (null .)

示例用法:

> isListEmpty (filter even) [1..]
False

如果我错了,请提供预期函数调用的示例。

于 2013-01-27T01:55:45.703 回答
1

第一:发生错误是因为您将此函数视为只有一个输入,即列表。另一方面,您的类型签名请求一个函数 from atoBool和 twolists of type a.

第二:您说,您必须编写一个函数,该函数测试应用了过滤器功能的列表是否为空。但是您只测试,如果列表为空,则没有应用您的过滤器功能(您没有(就像我上面描述的那样)甚至对该功能做任何事情。

第三:一点提示:从

isListEmpty f xs | length xs == 0 = True
                 | otherwise      = ...  ||  isListEmpty f ...

你必须为.... ||代表布尔“或”,如果你不知道的话。

于 2013-01-27T01:51:57.967 回答
1

你可以这样做:

null $ (filter (>2) [2,1,0]) ==> True
null $ (filter (>2) [2,1,9]) ==> False

和 :

null :: [a] -> Bool
null [] = True
null _  = False

或者使用 HOF(如前所述,这个解决方案是错误的,我不使用 HOF)

hof_null filter 
    | (null $ filter) = True
    | otherwise       = False


not_null (filter (>2) [1,1,3]) ==> False
not_null (filter (>2) [1,1,1]) ==> True

……

最后一次尝试,(感谢 Davorak)

hof_null fn = null.fn
于 2013-01-27T01:53:15.837 回答