Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function composition and its representations

I wonder:

1) are the following functions exactly the same:

inc = (+1)
double = (*2)

func1 = double . inc
func2 x = double $ inc x
func3 x = double (inc x)
func4 = \x -> double (inc x)

2) why doesn't func5 compile?

func5 = double $ inc        -- doesn't work
like image 250
Incerteza Avatar asked Nov 27 '22 11:11

Incerteza


2 Answers

Are these functions exactly the same?

Actually, no! There are some very subtle differences. First of all, read about the dreaded monomorphism restriction. In short, class-polymorphic functions are given different types by default if they're "obviously" functions or not. In your code, this difference won't manifest, because inc and double aren't "obviously" functions and so are given monomorphic types. But if we make a slight change:

inc, double :: Num a => a -> a
inc = (+1)
double = (*2)

func1 = double . inc
func2 x = double $ inc x
func3 x = double (inc x)
func4 = \x -> double (inc x)

then in ghci we can observe that func1 and func4 -- which are not "obviously" functions -- are given a monomorphic type:

*Main> :t func1
func1 :: Integer -> Integer
*Main> :t func4
func4 :: Integer -> Integer

whereas func2 and func3 are given a polymorphic type:

*Main> :t func2
func2 :: Num a => a -> a
*Main> :t func3
func3 :: Num a => a -> a

The second slight difference is that these implementations may have (very slightly) different evaluation behavior. Since (.) and ($) are functions, you may find that invoking func1 and func2 requires a little bit of evaluation before they can run. For example, perhaps the first invocation of func1 3 proceeds like this:

func1 3
= {- definition of func1 -}
(double . inc) 3
= {- definition of (.) -}
(\f g x -> f (g x)) double inc 3
= {- beta reduction -}
(\g x -> double (g x)) inc 3
= {- beta reduction -}
(\x -> double (inc x)) 3

whereas the first invocation of, e.g, func4 3 gets to this point in a much more straightforward manner:

func3 3
= {- definition of func3 -}
(\x -> double (inc x)) 3

However, I wouldn't worry about this too much. I expect that in GHC with optimizations turned on, saturated calls to both (.) and ($) get inlined, eliminating this possible difference; and even if not, it's going to be a very small cost indeed, since this will likely happen only once per definition (not once per invocation).

Why doesn't func5 compile?

Because you don't want it to compile! Imagine it did. Let's see how we would evaluate func5 3. We'll see that we "get stuck".

func5 3
= {- definition of func5 -}
(double $ inc) 3
= {- definition of ($) -}
(\f x -> f x) double inc 3
= {- beta reduction -}
(\x -> double x) inc 3
= {- beta reduction -}
double inc 3
= {- definition of double -}
(\x -> x*2) inc 3
= {- beta reduction -}
(inc * 2) 3
= {- definition of inc -}
((\x -> x+1) * 2) 3

Now we are trying to multiply a function by two. At the moment, we haven't said what multiplication of functions should be (or even, in this case, what "two" should be!), and so we "get stuck" -- there's nothing further that we can evaluate. That's not good! We don't want to "get stuck" in such a complicated term -- we want to only get stuck on simple terms like actual numbers, functions, that kind of thing.

We could have prevented this whole mess by observing right at the beginning that double only knows how to operate on things that can be multiplied, and inc isn't a thing that can be multiplied. So that's what the type system does: it makes such observations, and refuses to compile when it's clear that something wacky is going to happen down the line.

like image 162
Daniel Wagner Avatar answered Dec 05 '22 02:12

Daniel Wagner


1) Yes. Those functions are all absolutely identical

2) To see why func5 doesn't work, just expand out its definition:

func5

-- Definition of `func5`
= double $ inc

-- Definition of `($)`
= double inc

-- Definition of `double`
= 2 * inc

-- Definition of `inc`
= 2 * (1 +)

The compiler is complaining because (1 +) is a function, and you can't double a function.

like image 25
Gabriella Gonzalez Avatar answered Dec 05 '22 02:12

Gabriella Gonzalez