我有一个问题,为什么这个函数不能与“:”一起使用,但可以与 || 一起使用 以及为什么将“:”替换为|| 我的意思是为什么不能写
包含 xs (y:ys) = 前缀 xs (y:ys) : 包含 xs ys
contains :: String -> String -> Bool
contains [] _ = True
contains _ [] = False
contains xs (y:ys) = prefix xs (y:ys) || contains xs ys
关键思想
用于:
建立一个列表答案,||
或&&
建立一个真/假答案,和/+
或*
建立一个数字答案。想想你正在结合什么——它不必一直:
都是。
细节
我想你的意思是问为什么你不能写
contains xs (y:ys) = prefix xs (y:ys) : contains xs ys
:
用于将元素粘合到列表的前面,因此它具有 type a -> [a] -> [a]
。这意味着你在左边放一个东西,在右边放一个列表。您经常在编写递归函数时使用它,例如,您可以定义
increase :: [Int] -> [Int]
increase [] = []
increase (x:xs) = x + 5 : increase xs
这x + 5
是一个Int
和increase xs
是一个[Int]
。
让我们看看你的功能。它的类型是contains :: String -> String -> Bool
这样的,它需要一个字符串,然后是一个字符串,然后给你一个布尔值。之后=
你就得到了prefix xs (y:ys)
。现在prefix
有相同的类型:prefix :: String -> String -> Bool
,所以现在我们给了它xs
,(y:ys)
它给了我们一个布尔值。
在行的末尾,我们也得到了contains xs ys
一个布尔值,所以如果我们把它们放在:
它们之间,我们就会得到一些类似的东西
False : True
但我们不允许这样做,因为True
它不是一个列表。(记住(:) :: a -> [a] -> [a]
。)你可以做False:[True]
(这将是[False,True]
,但这不是你想要的。
您需要检查是否xs
存在 - 无论是在前面(y:ys)
还是在后面。或的符号是||
。所以代码说
xs
如果它在(y:ys)
它的前面 (prefix xs (y:ys)
) 或者它在ys
(contains xs ys
) 中的某个地方,它就在里面。
里面有:
(put-in-front-of 符号) 它会说
xs
如果它在(y:ys)
它的前面(prefix xs (y:ys)
),则将那个答案放在这些答案的前面 - 它在ys
(contains xs ys
)中的某个地方。
这是没有意义的。这就是为什么您需要或 ( ||
) 不在 ( ) 前面的原因:
。