Haskell - 如何搜索一个列表的元素是否存在于另一个列表中

时间:2017-10-29 10:47:08

标签: list haskell

我试图在Haskell中定义一个函数来检查列表A中的元素是否都在列表B中并返回一个布尔值。

所以给出以下内容:

listb = [a,b,c,d]

function :: [char]->Bool

该函数应检查输入列表是否只包含listb的元素 输入列表也不能超过n 的长度。

这些是我尝试过的一些方法,但它们似乎都不起作用:

function :: [char] -> Bool
function xs = length xs == n && isElem xs

isElem :: [char] -> Bool
isElem (x:xs) = x  `elem` listb && isElem xs

有效输入失败。

我也尝试过:

function :: [char] -> Bool
function xs = length xs == n && whileValid xs

whileValid :: [char] -> Bool
whileValid (x:xs)
    |x `elem` listb = True && whileValid xs
    |otherwise = False

出于同样的原因失败了。

这些方法有什么问题,如何定义此功能才能使用?

3 个答案:

答案 0 :(得分:3)

听起来你正试图检查两个不相关的东西:

  1. 列表xs的元素是否是另一个列表{@ 1}}的元素的子集?

  2. ys的长度最多是xs吗?

  3. 最简单的方法是分别检查这些。

    n

    您可以通过将这些操作组合在一起来节省更多时间,但我的手机电池电量不足,所以我会留待以后使用。

答案 1 :(得分:3)

将概念概括为任何类型Eq类的实例,您可以按如下方式进行操作;

import Control.Applicative

exists :: Eq a => [a] -> [a] -> Bool
exists x y = any id $ (==) <$> x <*> y

*Main> exists [1,2,3] [3,4,5]
True
*Main> exists [1,2,3] [7,4,5]
False

答案 2 :(得分:2)

您的代码存在一些问题:

  1. 类型以大写字母开头,其中类型变量以小写字母开头,因此

    function :: [char] -> Bool
    

    不是你想要的,而是function :: [Char] -> Bool,我会写isSubSet :: String -> Bool或更一般的isSubSet :: Eq a => [a] -> Bool

  2. 通常在haskell中,您不使用像

    这样的全局常量
    listB :: [Char]
    listB = ['a'..'d']
    
  3. 而是参数化函数 - 所以

    isSubSetOf :: String -> String -> Bool
    isSubSetOf [] _ = True
    isSubSetOf small@(x:xs) big = (length small <= length big)
                               && (x `elem` big && isSubsetOf xs big)
    
    isSubSet x = isSubSetOf x listB
    
  4. 将是类型签名的正确实现,它是一个完整的函数,这是一种奇特的说法 - 处理所有输入类型的情况,你错过了列表的基本情况,即处理空列表。

    但它有一些(逻辑)错误需要解决:

    • 在每个步骤中检查length都没有必要,实际上根本没有必要 - 这会减慢你的算法速度!
    • 查看isSubSetOf "aab" "abbb"
    • 等测试用例