List 提高Haskell列表递归函数的效率

List 提高Haskell列表递归函数的效率,list,haskell,recursion,boolean,pattern-matching,List,Haskell,Recursion,Boolean,Pattern Matching,我已经编写了一个函数,它将比较两个列表并检查第一个列表是否是第二个列表的前缀,并且必须使用递归来完成 例如: prefix [1,2] [1,2,3] >True prefix [2,1,4] [2,1,13,4] >False 现在我已经这样做了,但我觉得效率很低: prefix :: [Int] -> [Int] -> Bool prefix (x:xs) (y:ys) | null xs = True |

我已经编写了一个函数,它将比较两个列表并检查第一个列表是否是第二个列表的前缀,并且必须使用递归来完成

例如:

prefix [1,2] [1,2,3]
>True
prefix [2,1,4] [2,1,13,4]
>False
现在我已经这样做了,但我觉得效率很低:

prefix :: [Int] -> [Int] -> Bool
prefix (x:xs) (y:ys)
|   null xs                         =   True
|   x == y && head xs == head ys    =   True && prefix xs ys
|   head xs /= head ys              =   False
我希望它可以做得更有效,并与一些更好的模式匹配。可以吗?

您根本不需要使用head功能。这使比较的数量增加了一倍。试试这个:

前缀::[Int]->[Int]->Bool 前缀[]u=真 前缀[]=False 前缀x:xs y:ys |x==y=前缀xs-ys |否则=假
Chad Gilbert的解决方案可以稍微简化:

prefix :: [Int] -> [Int] -> Bool
prefix [] _ = True
prefix (x:xs) (y:ys)
  | x == y = prefix xs ys
prefix _ _ = False
这不会影响性能,但它展示了一个语言特性:当一个模式上的所有防护都失败时,该匹配将被放弃,并将继续与下一个模式进行匹配

 Prelude > let prefix [] _ = True
 Prelude |     prefix _ [] = False
 Prelude |     prefix (x:xs) (y:ys) = if ( x==y) then prefix xs ys else False
示例:

  Prelude> prefix [1,3] []
  False
  Prelude> prefix [] [1,2,3]
  True
  Prelude> prefix [1,2] [1,2,3]
  True

哦,我明白了,是的,这确实有效,我现在发现了一个实例,我的实例没有,当我使第一个列表包含任何单个整数时,它将返回true。您能解释一下解决方案的:u部分吗?:[]匹配第一个列表比第二个列表长的情况,这意味着第一个列表永远不能是第二个列表的前缀。代码实际上可以缩短为[],因为我们已经在第一个列表中匹配了一个空的第一个列表pattern@GarethAllen-Stringer x:xs在这种情况下,模式匹配列表x的第一项和尾部xs,请参阅捕获丢失模式的一个好方法是使用-fwarn complete patterns或just-Wall运行GHC。通常,将{-OPTIONS_GHC-Wall-}写在文件顶部。