I have a question why this function cannot work with “:” but works with || and why “:” is replaced by ||
I mean why cannot write
contains xs (y:ys) = prefix xs (y:ys) : contains xs ys
contains :: String -> String -> Bool
contains [] _ = True
contains _ [] = False
contains xs (y:ys) = prefix xs (y:ys) || contains xs ys
Key idea
Use
:to build up a list answer,||or&&to build up a True/False answer, and+or*to build up a numerical answer. Think about what you’re combining – it doesn’t have to be:all the time.Detail
I think you mean to ask why you can’t write
:is for gluing an element to the front of a list, so it has typea -> [a] -> [a]. This means you put a single thing on the left and a list on the right. You often use that in writing recursive functions, for example, you could defineHere
x + 5is anIntandincrease xsis a[Int].Let’s look at your function. Its type is
contains :: String -> String -> Boolso it takes a String, then a String, then gives you a Bool. Straight after the=you getprefix xs (y:ys). Nowprefixhas the same type:prefix :: String -> String -> Bool, so now we’ve given itxsand(y:ys)it’s giving us a Bool.At the end of the line we’ve got
contains xs yswhich is a Bool too, so if we put:between them we’ve got something a bit likebut we’re not allowed to do that because
Trueisn’t a list. (Remember(:) :: a -> [a] -> [a].) You can doFalse:[True](which would be[False,True], but that’s not what you want anyway.You need to check whether the
xsis there – either at the front of(y:ys)or later on. The symbol for or is||. So the code saysWith the
:(put-in-front-of symbol) in it it would saywhich doesn’t make sense. That’s why you need or (
||) not in-front-of (:).