【问题标题】:Haskell: Check if the first list is a prefix of the secondHaskell:检查第一个列表是否是第二个列表的前缀
【发布时间】:2018-05-23 19:32:53
【问题描述】:

我正在尝试编写一个程序来检查第一个列表是否是第二个列表的前缀。例如,[5,6] 是 [1,5,6,7] 的前缀。这是我的工作代码,但基本上我不知道该怎么做。

prefix [Int] -> [Int] -> Bool 
prefix [] [] = [] 
prefix y (x:xs)  
| x == y    = prefix y xs 
| otherwise = 0 

有什么帮助吗?

【问题讨论】:

标签: list haskell int prefix


【解决方案1】:

如果我们查看类型,您的代码没有多大意义:

prefix [Int] -> [Int] -> Bool 
prefix [] [] = [] 
prefix y (x:xs)  
| x == y    = prefix y xs 
| otherwise = 0

由于这两个参数是列表 ([Int]),因此这意味着 y[Int]xIntxs[Int]。但是然后你比较x == y,你不能比较一个列表和一个元素。 (==) 定义为(==) :: Eq a => a -> a -> Bool

这里还有其他问题:你在第一个子句中返回了一个列表,但是返回类型是Bool,后来你返回了0(同样应该是Bool)。

如果我们定义一个函数,我们首先需要为它定义一个特定的模型。什么时候列表 l1 是列表 l2 的前缀?如果 l1 是一个空列表,那么 l1 总是一个前缀,而不管第二个列表的值如何,所以:

prefix [] _ = True

如果l1是一个列表(即(x:xs)),那么它在两种情况下不是前缀:(1)如果l2 是一个空列表; (2) 如果 l2 的第一项((y:ys)) 中的y 不等于x,则:

prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
                     | otherwise = ...

现在的问题是如何处理prefix (x:xs) (y:ys),以防x == y。在那种情况下,我们在两个列表上递归,所以prefix (x:xs) (y:ys) == prefix xs ys的结果(仅在x == y的情况下),所以:

                     | otherwise = prefix xs ys

或现在完整:

prefix :: [Int] -> [Int] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
                     | otherwise = prefix xs ys

我们可以进一步将表达式推广到Eq a => [a] -> [a] -> Bool,使其与任何类型a一起工作,这是一个Eq实例(所以在@987654351上定义了一个(==)实例@):

prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
                     | otherwise = prefix xs ys

我们也可以交换条件,因为通常正逻辑比负逻辑更容易理解:

prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x == y = prefix xs ys
                     | otherwise = False

现在我们可以进一步移除守卫,并使用(&&) :: Bool -> Bool -> Bool 代替:

prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) = x == y && prefix xs ys

【讨论】:

  • @CommuSoft 非常感谢!
【解决方案2】:

只需将我的两分钱留在这里,使用 Prelude 中的功能组合:

isPrefix :: Eq a => [a] -> [a] -> Bool
isPrefix l1 l2 = take (length l1) l2 == l1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2020-06-28
    相关资源
    最近更新 更多