I am trying to write a function that takes two lists (list1 & list2) expressed as strings as arguments and after recursively iterating list1 and comparing a value from list2. when the value of list1 and list2 are equal, the recursion should break and return the two lists (modified).
For example. list1= "abcdef". list2= "def"
pseudo code:
- for char in list1
- if char==list2[0] –> [char:] list2[1:]
In the case above this would be returning: "def" "ef"
What I got so far:
isEqual :: String -> String -> String ->String
isEqual (s : os) (p : ps)
| p /= s = isEqual os (p : ps)
| otherwise = s:os ps
However, I get the following error message from vs-code:
• Couldn’t match expected type ‘String -> String’ with actual type ‘[Char]’
Possible cause: ‘(:)’ is applied to too many arguments
In the expression: s : os ps In an
equation for ‘isEqual’:
isEqual (s : os) (p : ps)
| p /= s = isEqual os (p : ps)
| otherwise = s : os pstypecheck(-Wdeferred-type-errors)
Couldn’t match expected type ‘[Char] -> [Char]’
with actual type ‘[Char]’
The function ‘os’ is applied to one argument, but its type ‘[Char]’ has none
In the second argument of ‘(:)’, namely ‘os ps’
In the expression: s : os pstypecheck(-Wdeferred-type-errors)
>Solution :
Your type signature won’t work. The type signature:
isEqual :: String -> String -> String -> String
describes a function that takes three input strings and produces a single output string. In order to accept two input strings and produce two output strings, you need to write something like:
isEqual :: String -> String -> (String, String)
This function will return a pair or "tuple" of two strings. This is the standard way of returning two values, and you won’t find a reasonable way to return the two strings without pairing them like this.
After this change, all you need to do is adjust your otherwise case to return a pair (s:os, ps):
isEqual :: String -> String -> (String, String)
isEqual (s : os) (p : ps)
| p /= s = isEqual os (p : ps)
| otherwise = (s:os, ps)
This functions appears to do what you want:
λ> isEqual "abcdef" "def"
("def","ef")
When it comes time to use the result of this function call in a larger program, you can either use functions fst and snd to extract the two lists from the returned pair, or you can use pattern matching to name the two lists. For example:
main = do
let (lst1, lst2) = isEqual "abcdef" "def"
putStrLn $ "First list was " ++ show lst1
putStrLn $ "Second list was " ++ show lst2