Why doesn't this free definition work in Haskell?

I tried to execute the following function definition:

relativelyPrime xy = gcd xy == 1 

free point:

 relativelyPrime = (== 1) . gcd 

However, this gives me the following error:

 Couldn't match type 'Bool' with 'a -> Bool' Expected type: (a -> a) -> a -> Bool Actual type: (a -> a) -> Bool Relevant bindings include relativelyPrime :: a -> a -> Bool (bound at 1.hs:20:1) In the first argument of '(.)', namely '(== 1)' In the expression: (== 1) . gcd In an equation for 'relativelyPrime': relativelyPrime = (== 1) . gcd 

I do not quite understand. gcd takes two Ints / Integer, returns one Ints / Integer value, after which one Int / Integer is checked for equality "1". I do not see where my mistake is.

+6
source share
2 answers

This does not work because gcd requires two inputs, while the composition of functions provides only gcd one input. Consider the definition of the composition of the function:

 f . g = \x -> f (gx) 

Therefore, the expression (== 1) . gcd (== 1) . gcd equivalent to:

 \x -> (== 1) (gcd x) 

This is not what you want. Do you want to:

 \xy -> (== 1) (gcd xy) 

You can define a new operator to create a unary function with a binary function:

 f .: g = \xy -> f (gxy) 

Then your expression will look like this:

 relativelyPrime = (== 1) .: gcd 

In fact, the operator (.:) can be defined in terms of composition of functions:

 (.:) = (.) . (.) 

It looks like an owl, but they are really equivalent. So another way to write an expression:

 relativelyPrime = ((== 1) .) . gcd 

If you want to understand what is going on, take a look: What does (f.) Do. Does g mean in Haskell?

+7
source

when you commented on this - if you really want a version without a header, you can first use uncurry gcd to convert gcd to a version that accepts a single input (tuple):

 Prelude> :t uncurry gcd uncurry gcd :: Integral c => (c, c) -> c 

then check the box (== 1) and finally curry again for the original signature:

 relativeelyPrime = curry ((== 1) . (uncurry gcd)) 

your version does not work just because gcd creates a function if only the first argument is given, and this is not legal input for (== 1) , which expects a number.

+5
source

All Articles