Hartson
Hartson

Reputation: 23

Why using the composition operator allows you to avoid the need to explicitly refer the initial argument?

I can't seem to get my head around why the below code will not compile:

decode :: [Bit] -> String
decode xs = map  (chr . bin2int) . (chop8 xs)

But the below will:

decode :: [Bit] -> String
decode = map  (chr . bin2int) . chop8 

When we give the 2nd function a list, it applies chop8 to it, then maps (chr . bin2int) to the elements in the list produced.

So why doesn't the 1st example do the same? Are we not effectively doing the same thing, but just giving chop8 the argument in the function definition?

Thanks

Upvotes: 2

Views: 188

Answers (2)

Izaak Weiss
Izaak Weiss

Reputation: 1310

The definition of (.) is key here.

To give a simpler example:

decode1, decode2 :: Int -> Char
decode1 x = chr . (abs x)
decode2 = chr . abs

Now, the definition of (.) is f . g = \a -> f (g a), so we can use that in both of our definitions:

decode1 x = \a -> chr (abs x a)
decode2 = \x -> chr (abs x)

We can further simplify this, by moving the lambda parameters into the pattern match:

decode1 x a = chr (abs x a)
decode2 x = chr (abs x)

Obviously decode2 is the right funtion; decode1 doesn't even typecheck. abs only takes one argument, but decode1 calls it with 2! Furthermore, decode1 has an extra parameter, a, which we don't want.

Upvotes: 8

typedfern
typedfern

Reputation: 1257

The second version, using what is called point-free style, does not require the "xs" parameter because the expression map (chr . bin2int) . chop8 already produces a function of type [Bit] -> String - so all you have is to set decode = to the expression's value.

With the first version, you are explicitly passing the xs argument, so the expression to the right side of = should be of type Int. Since you are explicitly applying chop8 to xs, the result is a concrete list, not a function.

One solution is to explicitly apply map to the result of chop8:

decode xs = map  (chr . bin2int) $ (chop8 xs)

Note the replacement of . with $ - "apply function to parameter" instead of "compose function with another function"

Upvotes: 4

Related Questions