我一直试图理解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
isPrefixOf
和tails
功能代码是:
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
将列表而不是列表列表作为参数,它如何工作?
答案 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
的开头,则Char
与String
进行比较。现在,让我们回到any
:any :: (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"
很容易。
我希望我已经清楚地解释了它。 :)