Haskell - filter string list based on some conditions

I am new to this community. I am learning Haskell and have difficulty coding Haskell. I hope you help me.

I searched here and on Google without any success.

My problem ist like fowllows: I want to write a function that takes a list as a parameter:

myStringListFilter :: [String] -> [String] 

follow these steps:

  • Delete the first letter

     myStringListFilter myList = map tail strListe myList 
  • Filter out each item in the list that starts with "u" or "U".

     myStringListFilter myList = filter (ยดelemยด ['u', 'U']) (map tail strListe myList) 

Step two does not work. I get an error.

How can I reach a solution if I want the following:

 Input: ["butter", "chees", "aUbergine", "egg", "milk", "bUbble", "curry"] Output: ["chees", "egg", "milk"] 
+2
source share
3 answers

Type filter -

 filter :: (a -> Bool) -> [a] -> [a] 

therefore, if you want to filter the String list according to the predicate, you need the String -> Bool function, but what you wrote (`elem` ['u',U']) is of type Char -> Bool .

So you need a function

 beginsWithU :: String -> Bool 

The easiest way to determine it is

 beginsWithU (c:_) = c == 'u' || c == 'U' beginsWithU _ = False -- empty list 

Then you misunderstood how filter works, it saves elements that satisfy the predicate, you want to remove them, so you need to compose the predicate using not (or define it as doesn'tbeginWithU directly directly).

However, as 7stud points out , you actually don't want to change the items you want to keep the original list, which

 myStringListFilter myList = filter (not . beginsWithU) (map tail myList) 

or, without dots:

 myStringListFilter = filter (not . beginsWithU) . map tail 

. Therefore, you also need to include tail in the predicate, and it does not need a map , which will give

 myStringListFilter = filter (not . beginsWithU . tail) 

or, if the possibility that an empty String occurs in the input list should be handled kindly,

 myStringListFilter = filter (not . beginsWith . drop 1) 

since tail "" will *** Exception: Prelude.tail: empty list , whereas drop 1 "" will create "" .

But, since you want to keep the original list item, you can also define a predicate to directly look at the second character,

 secondCharIsU :: String -> Bool secondCharIsU (_:c:_) = c == 'u' || c == 'U' secondCharIsU _ = False myStringListFilter = filter (not . secondCharIsU) 
+8
source

Proposed Solution:

 beginsWithU (c:_) = c == 'u' || c == 'U' beginsWithU _ = False myStringListFilter myList = filter (not . beginsWithU) (map tail myList) ghci>myStringListFilter ["butter", "cheese", "aUbergine", "egg", "milk", "bUbble", "curry"] ["heese","gg","ilk"] 

... does not display the correct result.

map modifies the source lines, so filtering the list of lines with maps will not result in a list containing any of the source lines. The operator must filter the source list using a special filter:

 myFilter :: String -> String -> Bool myFilter notAllowedChars str = if head (tail str) `elem` notAllowedChars then False --if match, reject this string else True --if no match, include this string in result list ghci>filter (myFilter "uU") ["butter", "cheese", "aUbergine", "egg", "milk", "bUbble", "curry"] ["cheese","egg","milk"] 

free point:

 filterBy :: String -> String -> Bool filterBy notAllowedChars = not . (`elem` notAllowedChars) . head . tail 

Remember that an array of characters, such as ['u', 'U'], is the same as the string "uU".

+3
source

I am also a beginner, so maybe my explanation will help.

What's the point "." mean and what is called? For example, in this line:

filterBy notAllowedChars = no. ( elem notAllowedChars). chapter. Tail

The point performs the "composition of the function", where:

 (f1 . f2) xs 

defined as:

 f1 (f2 xs) 

This means that haskell takes a function to the right of the point, f2, and applies xs to it:

 (f2 xs) 

Haskell then takes the return value of f2 and applies it to f1:

 f1 retValFromf2 

Here is a simple example of using a function:

 func1 x = x * 2 func2 x = x + 10 dostuff x = (func1 . func2) x ghci> dostuff 0 20 

And how does the filter work here? I do not see any filter function in this line:

filterBy notAllowedChars = no. ( elem notAllowedChars). chapter. tail

This function creates a filter. This function replaces the non-point free function I provided first:

 myFilter :: String -> String -> Bool myFilter notAllowedChars str = if head (tail str) `elem` notAllowedChars then False --if match, reject this string else True --if no match, include this string in result list 

So, I should have better name a point-free function:

 createFilter notAllowedChars = not . (`elem` notAllowedChars) . head . tail 

What you see on the right is a chain of functional compositions, and the rightmost function is the tail. tail takes a list as an argument and returns a list. The returned list is then applied to the head. head takes a list as an argument and returns a single list item. Partial Function:

 (`elem` notAllowedChars) 

takes as an argument a single left-side elute that returns exactly the head, and elem returns Bool. does not accept Bool as an argument, for example. True, and returns Bool, for example. Lying. Note that when you connect functions together with a point, you must make sure that everything that the function returns to the right of the point is the argument that the function takes on the left side of the point.

  • What is "pointless" really?

I think this means that no argument is specified in the function definition. I like to think of it as an xs, which is a list of points, and when the xs member doesn't appear anywhere in the function definition, you wrote this function in a dotless style. A dot is not a dot. If the point was a "point", then something like this:

 not . (`elem` notAllowedChars) . head . tail 

... can hardly be called dot free.

In Haskell, if you have a function defined as follows:

 myfunc xs = head xs 

where xs appears on the right side on both sides of the equal sign, then, like the equation, you can cancel them by doing:

 myfunc = head 

Then if you call:

 myfunc xs 

you will get the same result as with the original definition of myfunc.

Now take a look at this function definition:

 myfunc xs = tail (head xs) 

In this case, if you remove xs from both sides, you will get:

 myfunc = tail (head) 

But tail takes the list as an argument, not a function, so this will result in an error. However, if you rewrite the right side of myfunc using function composition:

 myfunc xs = (tail . head) xs 

... then again you can undo xs from both sides:

 myfunc = tail . head 

And this is again a point-free style. As for why you would bother to rewrite the function in a non-contact style, I'm not sure. At the moment, I think about it when I cheat that I can. You will find that when you learn computer programming language, you will learn a bunch of tricks. Sometimes you donโ€™t know why a trick is useful when you study it. You just have to admit the fact that being a beginner, you cannot always understand why the trick is useful. Only when you become more experienced does the usefulness of a certain trick become apparent.

In any case, writing a function in the style of point free does not affect the operation of the function, so do not worry about it if you do not understand it. As you learn more about Haskell, you can do some of the more advanced things.

My intention is to uncover Haskell

You should understand that 1) In my opinion, Haskell is an extremely complex language, 2) you can never "know" a programming language. The level of understanding is endless. So, the more you learn and use the language, the more you will learn about it. This means that no matter how expert you are in the language, you will still come across code that is difficult or impossible to understand.

@ 7Stud

... does not display the correct result.

As I wrote above, Daniel Fisher's code works just fine like yours. Could you tell me what you mean?

I published an example of Daniel Fisher and his result. If you compare this output with the output published in your operating processor, they do not match.

+1
source

Source: https://habr.com/ru/post/1480299/


All Articles