你好,我是haskell的初学者,我在比较/匹配具有给定字符串作为参数的集合列表中的字符串时遇到问题。
我想要实现的是:
我有一个清单
colorTypes = ["red" , "blue" ,"yellow" , "green" ]
我要做的是使用Data.List中的isInfixOf函数,使一个函数将给定的字符串与List的每个元素进行比较,并根据isInfixOf的结果返回一个模式
如果我使用函数的示例:
getColorData colorTypes "red"
它应该返回
[1, 0, 0, 0]
我尝试过的是:
import Data.List
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
我收到错误:使用此函数解析模式为:isInfixOf中的错误
我也尝试了这种情况
getColorData :: [String] -> String -> [Int]
getColorData (g:h:j:k) str = case (g:h:j:k) of
isInfixOf g str -> [1, 0, 0, 0]
isInfixOf h str -> [0, 1, 0, 0]
isInfixOf j str -> [0, 0, 1, 0]
isInfixOf k str -> [0, 0, 0, 1]
这也行不通,并且出现无法匹配的类型错误。
我不知道我的方法是否错误,或者是否有其他方法可以得到我想要的东西,但我会感谢您的帮助
答案 0 :(得分:2)
问题出在这里,您使用以下模式进行匹配:
getColorData (g:h:j:k) str
此处g
,h
和j
是列表的 heads (第一元素),而k
是 >列表的(其余项)。因此k
的类型为[String]
,不是 String
。
我们可以使用[g,h,j,k]
来修复它,它是四个元素的列表:
getColorData :: [String] -> String -> [Int]
getColorData [g,h,j,k] str
| isInfixOf g str = [1, 0, 0, 0]
| isInfixOf h str = [0, 1, 0, 0]
| isInfixOf j str = [0, 0, 1, 0]
| isInfixOf k str = [0, 0, 0, 1]
| otherwise = []
但它仍然不是真正好的设计。由于对于包含少于或多于四个元素的列表,此函数将出错。我也不确定使用isInfixOf
条件是否是个好主意:这意味着列表的顺序有时可以确定结果是什么:两个元素被交换的列表可能会导致不同。最后,代码是非常重复的(不遵循 D 而不是 R 重复 Y 我们自己的原则)。
一个更优雅的版本可能是:
getColorData :: Eq a => [a] -> [a] -> Maybe [Int]
getColorData [] _ = Nothing
getColorData (x:xs) s | isInfixOf x s = Just (1: map (const 0) xs)
| otherwise = fmap (0:) (getColorData xs s)
在这里,我们让它适用于两个a
具有相等关系的任何类型a
。此外,它适用于所有长度的列表。如果找不到元素,它将返回Nothing
,并返回Just e
和e
实体向量,并以列表的长度作为维数。