Aleksandr
Aleksandr

Reputation: 1

Haskell list comprehension, adding a string between two strings

I am having trouble with a couple list problems. The first is supposed to insert a string between strings, as long as the strings are the same length, ie inserts "da" [("so","ed"),("c",""),("",""),("mo","le")] would return ["sodaed" "da" "modale"]

so far I have

inserts :: String -> [(String, String)] -> [String]
inserts str pairs = [[x,str,z] | (x,z) <- pairs, length (x) == length (z)]

inserts' :: String -> [(String, String)] -> [String]
inserts' [] [] = []
inserts' str [(x:xs),(y:ys)] 
    | (length y) == (length x) = (x, str, y) : inserts' str [xs,ys]
    | otherwise = inserts' str [x,ys]

I am getting a type error though matching [char] to string

Upvotes: 0

Views: 979

Answers (2)

yatima2975
yatima2975

Reputation: 6610

You're really close! I'm pretty sure the error message you're getting is something different than not being able to match [Char] and String though, because these are the same!

Let's see what happens when we remove the type signature on inserts (I'm doing this in ghci, but you can of course try it via a file as well):

Prelude> let inserts str pairs = [[x,str,z] | (x,z) <- pairs, length x == length z]
Prelude> :t inserts
inserts :: [a] -> [([a], [a])] -> [[[a]]]

OK, that's a pretty general type. As you might know, String is the same as [Char]. So if we substitute Char for a in the type of inserts, and replace [Char] by String, we can see that the inserts can specialize to String -> [(String,String)] -> [[String]].

So the arguments match, but the result has one level of lists too many. That's pretty logical, since x,str and z are strings, so [x,str,z] is a list of strings. All that's needed is to concatenate these three strings into one.

Either you can append the lists 'by hand', using x ++ str ++ z as the expression on the left side of the list comprehension, or you could use concat [x,str,z] to do it; concat flattens a list of lists (of Characters in this case) into a list.


For your second try, you can use something similar instead of the three-tuple of strings (x, str, y), do you see what you need to do?

Upvotes: 2

thor
thor

Reputation: 22460

For the type to be correct, I think for the first function should be:

inserts :: String -> [(String, String)] -> [String]
inserts str pairs = [x ++ str ++z | (x,z) <- pairs, length (x) == length (z)]

or

inserts :: String -> [(String, String)] -> [[String]]
inserts str pairs = [[x,str,z] | (x,z) <- pairs, length (x) == length (z)]

, depending on your needs.

Upvotes: 0

Related Questions