2

I need to write on a module to be run on GHCi, with a function composition to the same function. This (The classic fog(x) = f(g(x))) runs:

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

The problem appears when I try to write it like this

(.) f f = (\x -> f (f x)).   (fof(x) = f(f(x)))

GHCi says:

"Conflicting definitions for `f'
 Bound at: Lab1.hs:27:9
           Lab1.hs:27:12"

Line 27:9 appear on the first time f and line 27:12 appear f again.

Why doesn't Haskell understand (.) f f = (\x -> f (f x))?

Community
  • 1
  • 1
m4verick
  • 89
  • 2
  • 13
  • 2
    Are you trying to pattern match for the case that both arguments are equal? Because in that case you don't just have a syntactical problem (need to use different names for different arguments) but also a conceptual problem (equality for functions is - in general - undecidable). – DanielM Sep 22 '14 at 12:58
  • Do you want `twice f = \x -> f (f x)`? – Tom Ellis Jan 30 '15 at 18:12

2 Answers2

7

As the error message says, you have conflicting definitions for f in the definition (.) f f = (\x -> f (f x)). You are binding the name f to both the first and second arguments to (.), so ghci doesn't know which argument to use when evaluating the expression f x.

There is nothing wrong with defining (.) using the pattern (.) f g, and then calling it with two arguments that happen to be the same.

sjy
  • 2,702
  • 1
  • 21
  • 22
  • But i need to write like (.) f f , I know that (.) f g is correctly write cose i run and probe on GHCI. I think it has to be a form to write (.) f f correctly, to me its a syntacs problem. – m4verick Sep 22 '14 at 03:35
  • 1
    user3421938: nope, you can't do it: λ let doesThisWork nope nope = nope :44:18: Conflicting definitions for ‘nope’ Bound at: :44:18-21 :44:23-26 In an equation for ‘doesThisWork’ – rampion Sep 22 '14 at 03:39
7

In Haskell, arguments to a function must have unique names. Using the same name for another argument is not allowed. This is because

foo x y = ...    ===    foo = (\x-> (\y-> ...))

and if y where replaced with x, the second x would just shadow the first inside the ... body: there would be no way to reference the first x from there.

You can just define twice f x = f (f x):

Prelude> :t twice
twice :: (t -> t) -> t -> t
Prelude> twice (+1) 4
6


Alternatively, f (f x) = (.) f f x = join (.) f x:

Prelude Control.Monad> :t join (.)
join (.) :: (b -> b) -> b -> b

join is defined in Control.Monad. For functions, it holds that join g x = g x x. It is also known as W combinator.

E.g. print $ join (.) (+1) 4 prints 6.

Community
  • 1
  • 1
Will Ness
  • 70,110
  • 9
  • 98
  • 181