元组模式匹配列表Haskell

时间:2017-10-17 23:22:41

标签: list haskell pattern-matching

我正在尝试实现一个函数,其中我有一个2元组列表,它返回对应于True的元组。第一个字符是String,第二个字符是布尔值。这就是我想要的:

pack  [ ("a", True), ("b", False), ("c", False), ("d", True) ]
       returns [ ("a", True), ("d", True)  ]

这是我的代码:

pack :: [String] -> [Bool] -> [(String, Bool)]
pack [] [] = []
pack (x:xs) [] = []
pack [] (y:ys) = []
pack (x:xs) (True:ys) = (x, True) : pack xs ys
pack (x:xs) (False:ys) = pack xs ys

我只能通过输入

来获得{return [(“a”,True),(“d”,True)]}
pack ["a", "b", "c", "d"] [True, False, False, True]

这不是我想要的,我很困惑如何处理这个问题。任何帮助,指导或链接都将非常感激。

1 个答案:

答案 0 :(得分:2)

我将使用您尝试实施的内容的说明向您展示我的解决方案的步骤。希望这有助于您在未来融合自己的解决方案。

如果我改写它,你想要一个具有以下签名的函数:

pack :: [(String, Bool)] -> [(String, Bool)]

也就是说,你有一个2元组列表(第一个元素是String,第二个元素是Bool),你想得到一个相同类型的列表

您希望过滤此列表的所有元组,并仅保留True值的元组。前奏碰巧只有一个功能:

filter :: (a -> Bool) -> [a] -> [a]

filter的第一个参数,一个名为谓词的函数a -> Bool,允许您定义要在第二个参数中保留的内容(第一个[a] })。

请注意,a可以是任何类型,因此我们可以将a替换为(String, Bool)filter将具有以下类型:

filter :: ((String, Bool) -> Bool) -> [(String, Bool)] -> [(String, Bool)]

它开始越来越接近pack的目标签名了!我们缺少的是谓词(String, Bool) -> Bool,它会告诉filter我们想要保留的内容:

isTrue :: (String, Bool) -> Bool
isTrue (_, True)  = True
isTrue (_, False) = False

最后,我们可以packfilter来实施isTrue

pack :: [(String, Bool)] -> [(String, Bool)]
pack = filter onlyTrue

您在评论中提到您不想使用任何“内置”功能。让我们摆脱filter,然后将pack写得更接近你发布的原始风格:

pack [] = []
pack (x:xs)
    | isTrue x  = x : pack xs
    | otherwise = pack xs