
Hi everybody, today somebody on IRC (#haskell on Freenode) jokingly submitted the following to lambdabot:
(.) (.) It turned out that (.) (.) :: (a1 -> b -> c) -> a1 -> (a -> b) -> a -> c. I got interested in why that is so, but unfortunately I have not been able to figure this out by myself yet. I know that partial application is used, but don't know to what it would expand to and why. Could someone please explain? (I asked on the channel, but nobody did answer so I thought I'd try my luck here.)
Regards, MoC

Am Montag 21 September 2009 21:47:40 schrieb MoC:
Hi everybody,
today somebody on IRC (#haskell on Freenode) jokingly submitted the
following to lambdabot:
(.) (.)
It turned out that (.) (.) :: (a1 -> b -> c) -> a1 -> (a -> b) -> a -> c. I got interested in why that is so, but unfortunately I have not been able to figure this out by myself yet. I know that partial application is used, but don't know to what it would expand to and why. Could someone please explain? (I asked on the channel, but nobody did answer so I thought I'd try my luck here.)
And it's not futile :) The type of (.) is (forall a, b, c.) (b -> c) -> (a -> b) -> a -> c Now, to not get confused, choose different type variables for the type of the first (.) and the second, say the first has type (b -> c) -> (a -> b) -> a -> c and the second has type (v -> w) -> (u -> v) -> u -> w === (v -> w) -> ((u -> v) -> (u -> w)) Feeding it as an argument to the first, we must unify this type with the type of the first (.)'s (first) argument, (b -> c), thus b = (v -> w) c = (u -> v) -> u -> w and the type of (.) (.) becomes (a -> b) -> a -> c, which is (a -> (v -> w)) -> a -> ((u -> v) -> u -> w) by what we got for b and c. Now remove those parentheses which aren't necessary because (->) is right associative, to get (a -> v -> w) -> a -> (u -> v) -> u -> w and rename the type variables to get exactly lambdabot's answer.
Regards, MoC

Daniel Fischer wrote:
(v -> w) -> (u -> v) -> u -> w === (v -> w) -> ((u -> v) -> (u -> w))
Feeding it as an argument to the first, we must unify this type with the type of the first (.)'s (first) argument, (b -> c), thus
b = (v -> w) c = (u -> v) -> u -> w
and the type of (.) (.) becomes (a -> b) -> a -> c, which is
(a -> (v -> w)) -> a -> ((u -> v) -> u -> w)
by what we got for b and c.
I started with the same approach but for whatever reason failed to see the "feeding" process so I basically said that b = (v -> w) -> ((u -> v) -> (u -> w)) which, of course, was a dead end. It's interesting that I did not have problems with acknowledging a feeding process with "simple" (for I don't know the proper term) types, e. g. it was clear to me that if I feed f :: (a->b)->c with g :: Integer -> Integer a and b in this case would be Integer in this case. I think I'm not completely used to functions being value, yet. ;) Anyway, thank you very much for helping out (actually to both replies) and in this case also for clarifying. Regards, MoC

The type of `(.)` is (.) :: (b->c) -> (a->b) -> a -> c it can be defined as: (.) f g x = f (g x) So, let f = (.), then we can plug that in and make it infix in the defn to get: (.) (.) g x q y = g x . q $ y I had to add a few variables there to make it pointed, as opposed to the more succint semipointfree version: (.) (.) g x = (.) g x So we can see that this function, `(.) (.)` takes four arguments, a function on 2 inputs (g, because (.) is going to feed it another one, and it's taking one already, in the form of x). One of the variables of appropriate some arbitrary type `t` (since g is the only thing that will ever see it, you can think of it as a kind of index to an indexed family of functions of type `b->c`.) giving `(.) (.)` just `x` will reduce the type to something you should recognize, that is if: foo x = something in (\ g q y -> (.) (.) g x' q y) then foo has type: foo :: (b -> c) -> (a -> b) -> a -> c eg, foo = (.) So, (.) (.) effectively says, "Given a indexed family of functions from `b -> c`, indexed by some type `t` compose the `t`th function with some function `q` from `a -> b`, and return a function of type `a -> c`. You might use it for something like mapping over a list at a given starting point, or something. HTH. /Joe On Sep 21, 2009, at 3:47 PM, MoC wrote:
Hi everybody,
today somebody on IRC (#haskell on Freenode) jokingly submitted the following to lambdabot:
(.) (.) It turned out that (.) (.) :: (a1 -> b -> c) -> a1 -> (a -> b) -> a - c. I got interested in why that is so, but unfortunately I have not been able to figure this out by myself yet. I know that partial application is used, but don't know to what it would expand to and why. Could someone please explain? (I asked on the channel, but nobody did answer so I thought I'd try my luck here.)
Regards, MoC _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (3)
-
Daniel Fischer
-
Joe Fredette
-
MoC