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

时间:2020-10-06 21:03:37

标签: string haskell

我需要编写一个函数,通过使用列表推导来检查子字符串是否在另一个字符串中。

我正在使用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一个带有函数check str的列表[[a]]列表,并且它不接受吗?

2 个答案:

答案 0 :(得分:3)

IsPrefixOf :: Eq a => [a] -> [a] -> Bool期望两个相同类型的列表(并且该类型应该是Option Explicit Sub Refresh() ' Define workbook ('wb'). Dim wb As Workbook Set wb = ActiveWorkbook ' Do. wb.RefreshAll ' Define Target Worksheet ('tgt'). Dim tgt As Worksheet Set tgt = wb.ActiveSheet ' Define Old Date Cell ('cel'). Dim cel As Range Set cel = tgt.Range("A1").End(xlDown) ' Check if Old Date Cell does not contain today's date. If cel.Value <> Date Then ' Does not contain today's date: ' Define New Date Cell ('cel'), the cell below Old Date Cell. Set cel = cel.Offset(1, 0) ' Write today's date to New Date Cell. cel.Value = Date Else ' Does contain today's date: ' Do nothing because Old Date Cell is becoming New Date Cell. End If ' Define Source Worksheet ('src'). Dim src As Worksheet Set src = wb.Worksheets("Portfolio") ' Write value from Source Cell to Target Cell. ' (Source Cell is next to New Date Cell). cel.Offset(0, 1).Value = src.Range("B3").Value End Sub 类型类的成员),因此例如,两个Eq是因为{{1} }是String的列表。

但是,您提供了StringChar)和String列表(substr的类型为String)。因此,这将不会进行类型检查。此外,多次使用check str将使[String]在效率低的 O(n 2 中运行。

您可以使用any :: Foldable f => (a -> Bool) -> f a -> Bool来检查可折叠元素(例如列表)中的任何元素是否满足谓词。我们还可以使用tails :: [a] -> [[a]]以更有效的方式获取列表的所有尾部(包括完整列表):

drop

我们可以进一步将其概括为与check str类型类成员的任何类型import Data.List(isPrefixOf, tails) contains :: String -> String -> Bool contains str substr = any (isPrefixOf substr) (tails str)的列表一起使用:

a

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

Eq

答案 1 :(得分:2)

问题是isPrefixOf需要一个String,但是您的check返回了一个字符串列表([String])。

解决方法是将isPrefixOf包装在any中,这会将功能映射到整个列表:

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)