How to write a recursion function in haskell

How to write a function in Haskell that takes a list and a number and removes all elements that exceed that number and returns a list.

delete [5, 4, 3, 9, 1] 5 should return [5,4,3,1]

I wrote the following method, which becomes an infinite loop, where it hits a greater than a given number. I exit [5,4,3, and then the program does not end.

remove l1 x = if (null l1 == True) then l1 else if (head l1 > x) then remove (drop 0 l1) x else ((head l1) : remove (tail l1) x) 

This is the first time I'm trying to use Haskell programs, please suggest me what I'm doing wrong here.

thanks

+4
source share
2 answers

Well, you are off to a decent start, but it’s important to note that you are not following the β€œHaskell” approach.

Let me show you a few different approaches to this problem:

Approach 1: Recursive Function

First of all, we could write a recursive function (like you) to solve this problem.

To do this, we first apply the base register (one that would not allow an infinite loop under normal circumstances). This should work:

 remove [] _ = [] 

It just says that if we want to remove items from an empty list, we get an empty list. It is so simple. _ means we don't care what the value of x .

Now we must identify our other cases. For this, I would use guards (I'm sure there are other approaches, the base file has been added for completion):

 remove [] _ = [] remove (x:xs) y | x > y = remove xs y | otherwise = x : remove xs y 

So, the first line ( remove (x:xs) y ) says that our function will accept a list (where x is the name of the chapter / first and xs is the rest).

The second line says that if x greater than y , consider the rest of the elements, and we don’t think that x is part of our final decision.

The third line ( otherwise catches all cases if it hits, and is similar to else in the if/elseif/else conditional block in other languages). If we get to this point, we know that it is not so that x > y so we will look at our other values ​​( xs ) and we will include x , but we are done with x .

Now this approach works decently, but there is a simpler one:

Approach 2: List comprehension

Using the list of concepts , we can create a very simple and powerful solution:

 remove xs y = [x | x <- xs, not (x > y)] 

If you've ever studied set-theory (in particular, set-construction notation ), this should look oddly familiar to you. Let me go through what each part means.

  • [...] - Something in brackets just means that we are building a list

  • x |... - means that our list will contain x such that ( | means "such that") ...

  • x <- xs, - x is an element of xs and (a comma means "and") ...

  • not (y > x) - It is not true that y greater than x

As you can see, this second approach almost exactly mimics your description of the problem. This is truly the power of Haskell, words and abstraction tend to almost display directly in Haskell code.

Approach 3: Using filter

As indicated below, the third option is to define it as such:

 remove y = filter (<=y) 

If the filter will contain only elements that are less than or equal to y. (Give credit to Daniel Wagner for this approach).

+12
source

You can use pattern matching in args functions and a filter with protection:

 remove [] x = [] remove (h:t) x | h > x = remove tx | otherwise = h : remove tx 

You can also use the filter function, it does what you need:

 remove lx = filter (<= x) l 
+7
source

All Articles