1

I'm trying to establish the best way to understand a series of embedded anonymous expressions such as:

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

In Haskell. I don't have too much trouble with simpler expressions such as:

(\x -> x + 1) 

Which states that the function takes a Number and returns a number: Num a => a -> a

But when things are embedded like this I get quite lost. My attempt to understand it is that the anonymous function pipes the argument from f to g to x right away, where I should then begin writing the typing as it is where the variable is used. But I've tried rationalizing maybe four or five different explanations and I keep getting caught up on what looks like a recursive function call in the innermost function.

Can the typing of this problem be figured out in an easier manner?

3 Answers 3

4

This is just an example of currying. Haskell provides syntactic sugar for this:

\f g x -> f (g x)

In either case, applying the function to an argument foo1 returns the function

\g x -> foo1 (g x)

Applying this to a function foo2 returns another function

\x -> foo1 (foo2 x)

which, if applied to yet another argument bar would return the value computed by foo1 (foo2 bar).


In a language like Python, it would look like

compose1 = lambda f: lambda g: lambda x: f(g(x))

Since Python functions are not curried by default, this is a distinct function from compose2 = lambda f,g,h: f(g(x)). The difference between the two would be how you use them.

compose1(foo1)(foo2)(bar)
compose2(foo1, foo2, bar)

Written out using def statements, compose1 would look something like

def compose1(f):
    def _1(g):
        def _2(x):
            return f(g(x))
        return _2
    return _1
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! The \f g x -> f (g x) really "fixed" my perspective. I understand it now.
3

You don't need to overthink this. (\f -> (\g -> (\x -> f (g x) ) ) ) is just a function of an argument f with some result... which happens to be again a function, but it's in principle no different from a function whose result is a number. It's just some blackbox...

\f -> ██

Now, when you actually apply this lambda to some f, you get access to the blackbox. For example, I can apply it to the sqrt function:

(\f -> ██) sqrt
  ≡ ██
  = \g -> ██₂

Ok, another lambda which yields some blackbox. Let's apply that one to (^2)

(\g -> ██₂) (^2)
  ≡ ██₂
  = \x -> ██₃

Now that blackbox isn't so dark: it's just f (g x), where f, g and x are arguments we've already applied:

(\f -> (\g -> (\x -> f (g x) ) ) ) sqrt (^2)
  ≡ \x -> sqrt (x^2)

Of course that's just one example. Generally, that big lambda of yours takes two functions and gives you the composition of both functions. Of course this is better written as

\f g x -> f $ g x

or in fact simply .

1 Comment

Thank you. I was not reading it quite as a function composition with two function arguments. It makes sense once I do that!
1

Think of the entire lambda function as a black box. From the signature we know there are three arrows "->" separating each argument. This tells you that this black box receives 3 actual arguments: f g x. It applies f to the result of applying g to x. It's easier to understand by looking at its named function equivalences.

compose f g x = f (g x)
compose' f g = \x -> f (g x)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.