Question

I want to write a replicate-like function that works like this :

repli "the" 3 = "ttthhheee" and repli "jason" 4 = "jjjjaaaassssoooonnnn"

Here is the code that I wrote :

myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n)

The error I get is this :

Couldn't match expected type `[a]' against inferred type `Char'
     Expected type: [[a]]
     Inferred type: [Char]
   In the first argument of `repli', namely `"jason"'
   In the expression: repli "jason" 3

How can I fix this? Thanks.

Was it helpful?

Solution 2

myrepli is expecting a list and an integer. However, the definition of repli calls it with x, which is an item, not a list of items.

I imagine you either want to change myrepli to take a single item as argument, or you want to change repli to pass [x] instead of just x. (I would suggest the former rather than the latter.)

OTHER TIPS

For problems with types, here's a trick that has helped me immensely. Whenever I am completely baffled by a message like this, I do the following:

  • If there's a type signature on the function in question, remove it and see if anything changes. If it compiles, ask ghci what the type is (using :t). If it doesn't compile, at least the error message may differ enough to give you another clue.
  • If there's no type signature, add one. Even if it doesn't compile, the error message may give you another clue.
  • If that doesn't help, then temporarily add type declarations on each of the expressions in the function. (Often you'll need to break up some of the expressions to see what's really going on. You may also need to temporarily enable the ScopedTypeVariables pragma.) Compile again and check the error messages.

That last one is more work, but I've learned a lot from that exercise. It usually pinpoints the exact place where there's a mismatch between what I think the type is and what GHC thinks the type is.

So let's begin by adding type signatures to your code:

myrepli :: [a] -> Int -> [a]
myrepli []  n = []
myrepli [x] 0 = []
myrepli [x] n = (x:(myrepli [x] (n-1)))


repli :: [a] -> Int -> [a]
repli [] n = []
repli (x:xs) n = (myrepli x n) ++ (repli xs n) -- triggers a compiler error

Ah, now we get a compiler error:

amy.hs:9:27:
    Couldn't match expected type `a' with actual type `[a]'
      `a' is a rigid type variable bound by
          the type signature for repli :: [a] -> Int -> [a] at amy.hs:7:10
    In the first argument of `myrepli', namely `x'
    In the first argument of `(++)', namely `(myrepli x n)'
    In the expression: (myrepli x n) ++ (repli xs n)

The problem is in the call to myrepli x n. The function myrepli expects a list/string, but you're passing it a single character. Change that last line to:

repli (x:xs) n = (myrepli [x] n) ++ (repli xs n)

At that point you will find other errors in your code. But rather than fix your code, let me show you another way to do it:

repl (x:xs) n = (myReplicate x n) ++ (repl xs n)
repl [] _ = []

-- You could use the library function "replicate" here, but as a
-- learning exercise, we'll write our own.
myReplicate a n = take n (repeat a)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top