Haskell:检查第一个列表是否是第二个列表的前缀

时间:2017-12-09 21:12:06

标签: list haskell int prefix

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

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

有什么帮助吗?

2 个答案:

答案 0 :(得分:4)

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

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

由于这两个参数是列表([Int]),因此这意味着y[Int]xInt,{{ 1}}是xs。但是你比较[Int],你无法将列表与元素进行比较。 x == y定义为(==)

此处还有其他问题:您在第一个子句中返回一个列表,但返回类型为(==) :: Eq a => a -> a -> Bool,稍后您返回Bool(同样,它应该是0 1}})。

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

Bool

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

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,使其适用于任何<{em>类型a Eq实例(因此有{{} 1}} (==)上定义的实例):

a

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

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

答案 1 :(得分:0)

只需将我的两美分放在 Prelude 的功能组合中即可:

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