Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to write a recursive function in Haskell that takes two lists as arguments and returns two list when a condition is met

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  • 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
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading