
iliali16 wrote:
take :: Integer -> [Integer] -> [Integer] take _ [] = [] take n xs |x < lenghtList xs = (take (n-1) xs :[]) |otherwise = xs I have decleared lenghtList before.
The wrong expression "xs:[]" indicates a major misunderstanding; it worries me alot because you also say you understand well. This makes help nearly impossible because if I go back to the basic, which is exactly what is needed, you think you can skip it. When you're given a list, there are two cases, as you know. One fits the pattern [], and your code has successfully caught that. The other fits the pattern x:s, the x being the first element of the list and the s being the remaining list. I'll say more because I have a point to make. For example if the given list is [3,1,4], and you match it against the pattern x:xs, then x refers to 3 and xs refers to [1,4]. The point I want to make is that x refers to 3, not [3], that x refers to the number, not a sublist; s does refer to a sublist. Turn it around, if you have a number 3 and a list of numbers [1,4], you can put them together, 3 first, with 3:[1,4]. That will give you [3,1,4]. Again, the point is that it is not [3]:[1,4], that's wrong; it is 3:[1,4]. Therefore things like [2,1]:[7,5] and [1,4]:[] are also wrong. (What if you really want to put together [2,1] and [7,5]? There is a way, but it's off-topic today.) Now I can talk about take. If the list is too short, you already handle that, so I just assume the list is long enough, e.g., "take 2 [3,1,4,7]". There is a recursion here, but it's largely on n, not so much on the list. The base case is "take 0 blahblah", and no matter what blahblah happens to be, and no matter how long blahblah is, no one cares, the correct answer is []. take 0 _ = [] The inductive case is when n is non-zero, and since I can assume the list is long enough (you already have code for the short case), I can just assume it matches the pattern x:s (in fact you also already have code for the [] case). It is possible to apply the pattern x:s to "decompose" the list and still have the name xs refer to the whole list; it looks like take n xs@(x:s) | n < lengthList xs = ... If the list is [3,1,4,7], then xs is still [3,1,4,7], x is 3, s is [1,4,7]. What can you do with these data? You want to extract the first n guys. You can extract the first guy, that is x then use recursion to extract n-1 more guys, but skipping x, that is n-1 guys from s but not xs: take (n-1) s then you put them together, x first, that is x : take (n-1) s The whole line of code looks like take n xs@(x:s) | n < lengthList xs = x : take (n-1) s If you call "take 2 [3,1,4,7]", n is 2, x is 3, s is [1,4,7], you get take 2 [3,1,4,7] -> 3 : take (2-1) [1,4,7] we trust in recursion -> 3 : [1] = [3,1] Eventually someone will tell you that the test "n < lengthList xs" is unnecessary and, moreover, slows things down tremendously (not just slightly). Eventually someone will also tell you "what if n is negative", and you have to make a decision about that. They are right. But I will call it a day.