简体   繁体   中英

Haskell - How to write (.) f f = (\x -> f (f x))

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 (.) ff = (\\x -> f (fx)) ?

As the error message says, you have conflicting definitions for f in the definition (.) ff = (\\x -> f (fx)) . 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 fx .

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

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 fx = f (fx) :

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


Alternatively, f (fx) = (.) ffx = join (.) fx :

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

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

Eg print $ join (.) (+1) 4 prints 6 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM