简体   繁体   中英

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

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 Char acters 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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM