用于检查Haskell中的子字符串是否在另一个字符串内的函数

kiz8lqtg  于 2022-11-14  发布在  其他
关注(0)|答案(3)|浏览(142)

我需要编写一个函数,通过使用列表解析来检查一个子字符串是否在另一个字符串中。
我使用drop从一个字符串创建一个字符串列表,使用isPrefixOf将创建的字符串列表与子字符串进行比较。
下面是我的代码:

contains :: String -> String -> Bool
contains str substr = isPrefixOf substr (check str)
    where
    check :: String -> [String]
    check str
        |str==[]   = []
        |otherwise = [drop x str | x <- [0..length(str)-1]]

然而,我得到这个错误:

Tutorial2.hs:163:42: error:
    * Couldn't match type `[Char]' with `Char'
      Expected type: [Char]
        Actual type: [String]
    * In the second argument of `isPrefixOf', namely `(check str)'
      In the expression: isPrefixOf substr (check str)
      In an equation for `contains':
          contains str substr
            = isPrefixOf substr (check str)
            where
                check :: String -> [String]
                check str
                  | str == [] = []
                  | otherwise = [drop x str | x <- [0 .. length (str) - 1]]
    |
163 | contains str substr = isPrefixOf substr (check str)

我想知道为什么我会得到这个错误,我该如何修复它。我假设这是因为我给isPrefixOf一个list a的列表,它不接受这个函数check string。

rekjcdws

rekjcdws1#

**IsPrefixOf :: Eq a => [a] -> [a] -> Bool**需要两个相同类型的列表(并且该类型应该是Eq类型类的成员),因此例如两个String,因为StringChar的列表。

然而,您提供了一个Stringsubstr)和一个String列表(check str的类型为[String])。因此,这将不会进行类型检查。此外,多次使用drop将使check strO(n2) 中运行,这是低效的。
你可以使用**any :: Foldable f => (a -> Bool) -> f a -> Bool来检查 predicate 是否满足可折叠列表中的任何元素,例如一个列表。我们还可以使用tails :: [a] -> [[a]]**来以更有效的方式获得列表的所有尾部(包括完整列表):

import Data.List(isPrefixOf, tails)

contains :: String -> String -> Bool
contains str substr = any (isPrefixOf substr) (tails str)

我们可以进一步将其推广为与作为Eq类型类的成员的任何类型a的列表一起工作:

import Data.List(isPrefixOf, tails)

contains :: Eq a => [a] -> [a] -> Bool
contains str substr = any (isPrefixOf substr) (tails str)

我们还可以通过使用**flip :: (a -> b -> c) -> b -> a -> c(.) :: (b -> c) -> (a -> b) -> a -> c**使函数 * 无点 *:

import Data.List(isPrefixOf, tails)

contains :: Eq a => [a] -> [a] -> Bool
contains = flip (any . isPrefixOf) . tails
i7uaboj4

i7uaboj42#

问题是isPrefixOf需要一个String,但您的check返回一个字符串列表([String])。
修复方法是将isPrefixOf Package 在any中,这样就可以将函数Map到整个列表:

contains :: String -> String -> Bool
contains str substr = any (isPrefixOf substr) (check str)
    where
    check :: String -> [String]
    -- ...

请注意,check等价于内置的tails(从技术上讲,它应该是length str,而不是length str - 1,但在本例中这并不重要),所以如果我们进行替换,我们将得到Willem's solution

contains :: String -> String -> Bool
contains str substr = any (isPrefixOf substr) (tails str)
vxf3dgd4

vxf3dgd43#

有一种更简单的方法(与目前为止发布的答案相比)来检查一个字符串是否是另一个字符串的子字符串。可以使用Data.List中的isInfixOf函数。
下面是签名:

isInfixOf :: Eq a => [a] -> [a] -> Bool

第一个参数是子字符串,第二个参数是要在其中检查子字符串的更大字符串。
以下是文档:)

相关问题