Search code examples
stringhaskellstring-lengthnon-exhaustive-patterns

Implementation of a program in which characters of a string repeated certain times in haskell


This is a question from my homework thus tips would be much likely appreciated.

I am learning Haskell this semester and my first assignment requires me to write a function that inputs 2 string (string1 and string2) and returns a string that is composed of (the repeated) characters of first string string1 until a string of same length as string2 has been created.

I am only allowed to use the Prelude function length.

For example: take as string1 "Key" and my name "Ahmed" as string2 the function should return "KeyKe".

Here is what I've got so far:

    makeString :: Int -> [a] -> [a]
    makeString val (x:xs)
        | val > 0 = x : makeString (val-1) xs
        | otherwise = x:xs

Instead of directly giving it two strings i am giving it an integer value (since i can subtitute it for length later on), but this is giving me a runtime-error:

*Main> makeString 8 "ahmed"

"ahmed*** Exception: FirstScript.hs: (21,1)-(23,21) : Non-exhaustive patterns in function makeString

I think it might have something to do my list running out and becoming an empty list(?).

A little help would be much appreciated.


Solution

  • I think this code is enough to solve your problem:

    extend :: String -> String -> String
    extend src dst = extend' src src (length dst)
        where
            extend' :: String -> String -> Int -> String
            extend' _ _ 0 = []
            extend' [] src size = extend' src src size
            extend' (x:xs) src size  = x : extend' xs src (size - 1)
    

    The extend' function will cycle the first string until is is consumed then will begin to consume it again.

    You can also make it using take and cycle like functions:

    repeatString :: String -> String
    repeatString x = x ++ repeatString x
    
    firstN :: Int -> String -> String
    firstN 0 _ = []
    firstN n (x:xs) = x : firstN ( n - 1 ) xs
    
    extend :: String -> String -> String
    extend src dst = firstN (length dst) (repeatString src)
    

    or a more generic version

    repeatString :: [a] -> [a]
    repeatString x = x ++ repeatString x
    
    firstN :: (Num n, Eq n ) => n -> [a] -> [a]
    firstN 0 _ = []
    firstN n (x:xs) = x : firstN ( n - 1 ) xs
    
    extend :: [a] -> [b] -> [a]
    extend _ [] = error "Empty target"
    extend [] _ = error "Empty source"
    extend src dst = firstN (length dst) (repeatString src)
    

    which is capable of taking any type of lists:

    >extend [1,2,3,4] "foo bar"
    [1,2,3,4,1,2,3]