+4  A: 

The two functions aren't really all that similar, if you look at them. What is the same are the first three "trivial" cases, but the last case does different things in both functions. You could also leave out the first two cases in either of those functions since they check the same thing on the same lists. So myIsInfixOf also works like this:

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf (a:as) [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

This really isn't the same as helpFunction, and doesn't repeat any nontrivial code.

Also you really want the second function to work independently from the first, since you want to check for every position in listB if every character of listA matches those in listB. To do this in a imperative program you would need nested loops, here you need a nested recursion best done with a helper function like you did. The issue is not that listA would somehow be lost without the helpFunction, the problem is that the algorithm requires helpFunction to run over the list independently of myIsInfixOf.

If you want to avoid manually implementing the recursion of myIsInfixOf by using more functions from the standard library you could use any and tails. For helpFunction probably explicit recursion is the way to go, but you could simplify the whole last case to:

helpFunction (x:xs) (y:ys) = (x == y) && helpFunction xs ys
sth
`myIsInfixOf [] []` should be `True`, but your version will return `False`.
Alexey Romanov
@Alexey: Right, fixed that
sth
OK, thanks for that.i thought that it could be a better way for code that, but i understand that my way is good enough :-).
moshe
Do you even need the first clause in your definition of myIsInfixOf? I think you could just pass two empty lists on to helpFunction and it would be correct. Also, I think I would rewrite the second clause using `or`, because it would seem simpler, but that's more a personal preference thing.
Noah Lavine
@noahlavine: The problem is that `tail listB` will fail if `listB` is empty.
sth
+2  A: 

Note that 1) you don't need the first clause in both cases, since [] list matches [] [] as well and you return the same result; 2) helpFunction listA listB == True is the same as helpFunction listA listB.

myIsInfixOf :: (Eq a) => [a] -> [a] -> Bool
myIsInfixOf [] list = True
myIsInfixOf list [] = False
myIsInfixOf listA listB | helpFunction listA listB = True
                        | otherwise =  myIsInfixOf listA (tail listB)

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

In the comment you said

the help function examine if the first element is inside the second one.

Actually, it doesn't. It checks if the second argument starts with the first one. That's why you need a different function. So a better name for helpFunction is myPrefixOf. This should help you eliminate another clause from the definition of myIsInfixOf.

Alexey Romanov
except that i already implemented also the myIsPrefixOf function :-),but it didn't occur to me, to use it here, but as you said, it's the right help function here. thanks :-).
moshe
+2  A: 

In line with a few of the suggestions Alexey Romanov and sth made, this would be my initial take on rewriting it:

import Data.List

myIsInfixOf xs ys = any (myIsPrefixOf xs) (tails ys)

myIsPrefixOf [] _ = True
myIsPrefixOf (x:_) [] = False
myIsPrefixOf (x:xs) (y:ys) = x == y && myIsPrefixOf xs ys

To more directly answer your actual question, note two things about this version:

  • You can kind of "save" the value of the first argument using partial application
  • You can eliminate a lot of the redundant code by using built-in recursive functions
camccann
`tails` is pretty easy to define without `import Data.List`, too. In any case, the standard library defines `isInfixOf` exactly like this, in terms of `any`, `isPrefixOf`, and `tails`, and defines `isPrefixOf` just like this too. :-)
ephemient
thanks for that :-).
moshe
A: 

I think you're confusing 'element' and 'argument' in your question, at least in some places. Also, what do you mean by 'untouchable'?

To come back to your question: You can do a pattern match and keep the original argument around by using so-called at-patterns:

myIsInfixOf listA@(x:xs) listB@(y:ys) = ...

This lets you refer to the entire first argument as listA, the first element of listA as x and the tail as xs (and same for the second argument). Is that what you meant?

yatima2975
i didn't get(yet) to this at-pattern in the book i'm reading, so maybe in the future they will discuss this.in untouchable, i mean that if i could leave the first element of the function(the list that i want to search for, in the second element(list) in the function) without changing, i didn't need another function.because every recursion, the first element is decreasing in one, and i can't compare the original element again.in your example, if i'm enter into recursion, the listA element is staying untouchable? i mean, it doesn't decrease itself every recursion?:-)
moshe