我需要编写一个函数,通过使用列表推导来检查子字符串是否在另一个字符串中。
我正在使用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]]列表,并且它不接受吗?
答案 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
的列表。
但是,您提供了String
(Char
)和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)