Reputation: 7164
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.
Upvotes: 1
Views: 227
Reputation: 8136
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:
:t
). If it doesn't compile, at least the error message may differ enough to give you another clue.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)
Upvotes: 8
Reputation: 62848
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.)
Upvotes: 3