Haskell:Data.List.isInfixOf函数如何工作?

时间:2015-02-13 23:24:02

标签: haskell functional-programming

我一直试图理解isInfixOf模块中的Data.List函数,但无济于事。这是代码:

     isInfixOf               :: (Eq a) => [a] -> [a] -> Bool
     isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack)

     -- Example:
     --
     -- >isInfixOf "Haskell" "I really like Haskell." -> True
     -- >isInfixOf "Ial" "I really like Haskell." -> False

如果列表中至少有一个项目满足条件,则any返回True。它的类型是(a -> Bool) -> [a] -> Bool

isPrefixOftails功能代码是:

    isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
    isPrefixOf [] _ = True
    isPrefixOf _ [] = False
    isPrefixOf (x:xs) (y:ys) = x == y && isPrefixOf xs ys

    tails :: [a] -> [[a]]
    tails xs = xs : case xs of 
                    [] -> [] 
                    _  : xs' -> tails xs'

    -- Example: 
    -- tails "abc" == ["abc", "bc", "c",""]

我已经阅读过关于curried函数和部分应用函数但我还不能理解它,我也无法理解这个特定函数是如何工作的。如果any将列表而不是列表列表作为参数,它如何工作?

1 个答案:

答案 0 :(得分:6)

如果isInfixOf needle haystack = any (isPrefixOf needle) (tails haystack) True needle细分isPrefixOf取消第一个元素,我们可以将any视为:{strong>返回haystack (即,取tails)。

不清楚吗?让我们尝试另一种方法,使用你的例子。

isInfixOf "Haskell" "I really like Haskell."

如果String[Char]相同,我们会为您的示例提供以下签名:

isInfixOf :: (Eq [Char]) => [Char] -> [Char] -> Bool

到目前为止一切顺利,是吧?我们来看any?不。让我们看isPrefixOf,因为它实际上是先调用并填充any的类型空白。

isPrefixOf :: (Eq Char) -> [Char] -> [Char] -> Bool

那么isPrefixOf在做什么?如果第一个Char(或Char s的数组)位于第二个String的开头,则CharString进行比较。现在,让我们回到anyany :: (a -> Bool) -> [a] -> Bool。但是,在示例中,传递给any的函数是isPrefixOf needle,即isPrefixOf "Haskell"。或者,换句话说,函数开始传递到类型为any的{​​{1}},实际上是(a -> Bool),或者,如果您愿意,则(String -> Bool)。得到它了?它是关于部分应用程序函数:([Char] -> Bool)最初(在我们的示例中),

isPrefixOf

但是,作为一个函数,我正在传递isPrefixOf :: (Eq Char) -> [Char] -> [Char] -> Bool ,因此它被修改为isPrefixOf "Haskell",这是一种根据您的想象不存在的符号。让它成为真正的"?只要带走看似奇怪的东西:

isPrefixOf "Haskell" :: "Haskell" -> [Char] -> Bool

isPrefixOf "Haskell" :: [Char] -> Bool

再次回到isPrefixOf "Haskell" :: String -> Bool 。你可以想象,any,现在,是

any

any :: (String -> Bool) -> [String] -> Bool

好吧,我认为现在any :: ([Char] -> Bool) -> [[Char]] -> Bool 的想法对你来说是完全清楚的。

tails

tails "I really like Haskell." :: String -> [String]

最后,执行是:

tails "I really like Haskell." :: [Char] -> [[Char]]

嗯,isInfixOf "Haskell" "I really like Haskell." = any (isPrefixOf "Haskell") (tails "I really like Haskell.") = any (isPrefixOf "Haskell") [ "I really like Haskell.", " really like Haskell.", "really like Haskell.", "eallylike Haskell.", "ally like Haskell.", "lly like Haskell.", "ly like Haskell.", "y like Haskell.", " like Haskell.", "like Haskell.", "ike Haskell.", "ke Haskell.", "e Haskell.", "Haskell.", "Haskell.", "askell.", "skell.", "kell.", "ell.", "ll.", "l.", ".", ""] 前缀"Haskell"很容易。

我希望我已经清楚地解释了它。 :)