Error using composition function in Haskell

Recently, I just started to study Haskell, more specifically on the topic of compiling functions, partial functions, maps, filters, and sectioning. In one exercise, Iโ€™m asked to modify the twoFilters function using function composition.

I read a few wikis on . but it's pretty hard for me to make it work correctly. As I understand it, it works by performing functions b . a b . a in alphabetical order and returning the result. In other words, x = foo a , and then foo b of x . However, after applying several โ€œoptions / possibilitiesโ€ using two filters, functions that I cannot compile due to errors.

 greaterThanOne :: Int -> Bool greaterThanOne = (>1) lessThanTen :: Int -> Bool lessThanTen = (<10) twoFilters :: [Int] -> [Int] twoFilters xs= filter lessThanTen (filter greaterThanOne xs) 

These two are unsuccessful attempts in which I most trust;

 twoFilters xs = filter (lessThanTen . greaterThanOne xs) twoFilters xs = filter (lessThanTen xs . greaterThanOne xs) 

Where, by reasoning, am I mistaken?

+4
source share
8 answers

Attempts that you were sure that this was a simple failure in your logic: the point operator works as follows:

(fg)(x) = f(g(x))

So, trying to calculate an example from 5 gives:

lessThanThen(greaterThanOne(5)) = lessThanTen(True) -- that can't be right, can it???

What you want is lambda and &: amp ;:

filter (\x-> (lessThanThen x) && greaterThanOne(x))

Alternatively, you can use two filters:

filter lessThanTen . filter greaterThanOne $

+3
source

Enter the wonderful world of applicative functors:

 import Control.Applicative greaterThanOne = (>1) lessThanTen = (<10) twoFilters = filter ((&&) <$> greaterThanOne <*> lessThanTen) twoFilters [1,2,3,4,5,6,7,8,9,10] -- [2,3,4,5,6,7,8,9] 

Read Learn about Haskell - Applicative Functors for a detailed explanation.

+3
source

You cannot compose these two functions like this. f . g f . g works like composition in mathematics, i.e. equivalent to f(g(x)) . This means that the outer function must accept an argument of the type returned by the inner function, in your case the outer function should be Bool -> Bool .

You can write your twoFilters using the composition operator as follows:

 twoFilters = (filter lessThanTen) . (filter greaterThanOne) 
+2
source

(.) expects a function that takes one argument and returns a value, but you pass it the Bool value to:

 lessThanTen . greaterThanOne xs 

which is wrong.

Here:

 lessThanTen xs . greaterThanOne xs 

you are trying to create two Bool values, but you had to build two functions that return Bool values.

+1
source

One of the problems is that a functional application has the highest priority. So lessThanTen . greaterThanOne xs lessThanTen . greaterThanOne xs tries to compose lessThanTen with the result of greaterThanOne xs (which does not work for starters, the function works with integers, not lists). Similarly, lessThanTen xs. greaterThanOne xs lessThanTen xs. greaterThanOne xs tries to compose the results of these function calls (assuming that they make sense first), rather than the functions themselves.

Another problem is misunderstanding . - (f . g) x equivalent to f (gx) , i.e. The result of the first function is an argument for the second. Thus, type g must be (a -> b) , and type f must be (b -> c) (both b are variables of the same type!). That you want to apply both functions to the same argument and join the results with && . There are no existing functions for this as far as I know (at least Hoogle did not find anything for (a -> Bool) -> (a -> Bool) -> a -> Bool ). You will need to make your own:

 both fgx = fx && gx 

Alternatively, you coudl just adhere to filtering twice (which is not as bad as it seems due to lazy evaluation) - filter (>1) $ filter (<10) xs .

+1
source

As I understand it, it works by performing functions b . a b . a in alphabetical order and returning the result. In other words, x = foo a and then foo b of x

It can be written in Haskell as

 let x = foo a in foo bx 

(where does foo come from?) but correct

 (b . a) x = let y = ax in by 

Or, in short:

 (b . a) x = b (ax) 

Now filter lessThanTen (filter greaterThanOne xs) has a similar form on the right side of this definition, if you remember that you can write it as (filter lessThanTen) ((filter greaterThanOne) xs) :

 ((filter lessThanTen) . (filter greaterThanOne)) xs 

Presumably what you really want is filter ??? xs filter ??? xs , but that should be enough to continue.

+1
source

You have it almost right. I find the easiest way to start learning functional composition with . is to use $ first.

So you have a list

 twoFilters xs = xs 

You want to filter with greaterThanOne

 twoFilters xs = filter greaterThanOne $ xs 

You also want to filter by lessThanTen

 twoFilters xs = filter lessThanTen $ filter greaterThanOne $ xs 

Now move from left to right, replacing all $ with . except last $

 twoFilters xs = filter lessThanTen . filter greaterThanOne $ xs 

Now you can use brackets instead of $ :

 twoFilters xs = (filter lessThanTen . filter greaterThanOne) xs 

Or just define a pointfree function:

 twoFilters = filter lessThanTen . filter greaterThanOne 

The staple-dependent version is the most important, I think. It shows that you are fusing two partially applied functions filter lessThanTen and filter greaterThanOne into one megafiltration function c . and then you apply a list to it. You need to bracket them because . binds less tightly than the application function through whitespace (a space can be considered a version of $ with a high degree of reliability). Remember that when you use . , you combine two functions together to form one megafunction.

It is important to verify the type signature .

 (.) :: (b -> c) -> (a -> b) -> a -> c 

The functions that you feed it must "line up" with very specific type signatures (they must be compatible for merging). But to be honest, the key is to learn to recognize when the application (the space) is associated more closely than you expect and mess up the types of function signatures that you are trying to create. One way or another, it was for me.

+1
source

The purpose of defining a function in Haskell is to often use it in another function. The compiler does some insertion of some functions when they can be found in another function. There are compiler suggestions called pragmas to get a compiler for inline code to improve performance. Haskell does this automatically, very well. Embedded code can also be directly included in the parent function. In addition, the enumerated methods resemble any Haskell function and fit perfectly into the functional structure. They are very well filtered with several criteria. He believes that this function can even be built into the program, because it is so brief.

fn xs = [x | x <-xs, x> 0, x <10]

0
source

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


All Articles