Re: [Haskell-cafe] Re: Very crazy

Chaddaï Fouché wrote:
2007/9/25, Andrew Coppin
: This is why I found it so surprising - and annoying - that you can't use a 2-argument function in a point-free expression.
For example, "zipWith (*)" expects two arguments, and yet
sum . zipWith (*)
fails to type-check. You just instead write
\xs ys -> sum $ zipWith(*) xs ys
(sum . zipWith (*)) xs ys == (sum (zipWith (*) xs)) ys
so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs) :: [a] -> [b], it can't work !
(sum.) . zipWith (*) works, but isn't the most pretty expression I have seen.
I'm still puzzled as to why this breaks with my example, but works perfectly with other people's examples... So you're saying that (f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z ? In that case, that would mean that (map . map) f xss ==> map (map f) xss which *just happens* to be what we want. But in the general case where you want f3 (f2 (f1 x y z)) there's nothing you can do except leave point-free.

On Sep 25, 2007, at 7:24 , Andrew Coppin wrote:
which *just happens* to be what we want. But in the general case where you want
f3 (f2 (f1 x y z))
there's nothing you can do except leave point-free.
You mean "leave point-ful". And the point-free version of that is (((f3 . f2) .) .) . f1 -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Tue, 2007-09-25 at 12:24 +0100, Andrew Coppin wrote:
Chaddaï Fouché wrote:
2007/9/25, Andrew Coppin
: This is why I found it so surprising - and annoying - that you can't use a 2-argument function in a point-free expression.
For example, "zipWith (*)" expects two arguments, and yet
sum . zipWith (*)
fails to type-check. You just instead write
\xs ys -> sum $ zipWith(*) xs ys
(sum . zipWith (*)) xs ys == (sum (zipWith (*) xs)) ys
so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs) :: [a] -> [b], it can't work !
(sum.) . zipWith (*) works, but isn't the most pretty expression I have seen.
I'm still puzzled as to why this breaks with my example, but works perfectly with other people's examples...
So you're saying that
(f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z
? In that case, that would mean that
(map . map) f xss ==> map (map f) xss
which *just happens* to be what we want. But in the general case where you want
f3 (f2 (f1 x y z))
there's nothing you can do except leave point-free.
In effect, yes. As many others have pointed out, you *can* do this point-free (all of lambda calculus can be re-written using the functions s f g x = f x (g x) k x y = x (1)), but it's not a good idea. Good style in Haskell as in any other language is a matter of taste, not rules. jcc (1) http://www.madore.org/~david/programs/unlambda/

On Tue, 2007-09-25 at 12:24 +0100, Andrew Coppin wrote:
Chaddaï Fouché wrote:
2007/9/25, Andrew Coppin
: This is why I found it so surprising - and annoying - that you can't use a 2-argument function in a point-free expression.
For example, "zipWith (*)" expects two arguments, and yet
sum . zipWith (*)
fails to type-check. You just instead write
\xs ys -> sum $ zipWith(*) xs ys
(sum . zipWith (*)) xs ys == (sum (zipWith (*) xs)) ys
so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs) :: [a] -> [b], it can't work !
(sum.) . zipWith (*) works, but isn't the most pretty expression I have seen.
I'm still puzzled as to why this breaks with my example, but works perfectly with other people's examples...
So you're saying that
(f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z
? In that case, that would mean that
(map . map) f xss ==> map (map f) xss
which *just happens* to be what we want. But in the general case where you want
f3 (f2 (f1 x y z))
there's nothing you can do except leave point-free.
As people have pointed out, you can do this, and in fact, can -always- do this, i.e. always write things "point-free." lambdabot's @pl command, as mentioned elsewhere, is a constructive proof of this. However, I'm composing this email to point out a historical fact: Essentially, "writing everything point-free" was Haskell Curry's research programme. See the field of combinatory logic of which he is one of the fathers.

Andrew Coppin wrote:
Chaddaï Fouché wrote:
2007/9/25, Andrew Coppin
: This is why I found it so surprising - and annoying - that you can't use a 2-argument function in a point-free expression.
For example, "zipWith (*)" expects two arguments, and yet
sum . zipWith (*)
fails to type-check. You just instead write
\xs ys -> sum $ zipWith(*) xs ys
(sum . zipWith (*)) xs ys == (sum (zipWith (*) xs)) ys
so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs) :: [a] -> [b], it can't work !
(sum.) . zipWith (*) works, but isn't the most pretty expression I have seen.
I'm still puzzled as to why this breaks with my example, but works perfectly with other people's examples...
So you're saying that
(f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z
? In that case, that would mean that
(map . map) f xss ==> map (map f) xss
which *just happens* to be what we want. But in the general case where you want
f3 (f2 (f1 x y z))
there's nothing you can do except leave point-free. Well, there's one thing. You can change your three argument function into a one argument function of a 3-tuple, and then change the composed function back again:
let uncurry3 = \f (x,y,z) -> f x y z curry3 = \f x y z -> f (x,y,z) in curry3 $ f3 . f2 . uncurry3 f1 In your earlier example, this would have been: curry $ sum . uncurry (zipWith (*))

On Wed, 2007-09-26 at 18:50 -0400, Steven Fodstad wrote:
Andrew Coppin wrote:
Chaddaï Fouché wrote:
2007/9/25, Andrew Coppin
: This is why I found it so surprising - and annoying - that you can't use a 2-argument function in a point-free expression.
For example, "zipWith (*)" expects two arguments, and yet
sum . zipWith (*)
fails to type-check. You just instead write
\xs ys -> sum $ zipWith(*) xs ys
(sum . zipWith (*)) xs ys == (sum (zipWith (*) xs)) ys
so you try to apply sum :: [a] -> Int to a function (zipWith (*) xs) :: [a] -> [b], it can't work !
(sum.) . zipWith (*) works, but isn't the most pretty expression I have seen.
I'm still puzzled as to why this breaks with my example, but works perfectly with other people's examples...
So you're saying that
(f3 . f2 . f1) x y z ==> f3 (f2 (f1 x) y) z
? In that case, that would mean that
(map . map) f xss ==> map (map f) xss
which *just happens* to be what we want. But in the general case where you want
f3 (f2 (f1 x y z))
there's nothing you can do except leave point-free. Well, there's one thing. You can change your three argument function into a one argument function of a 3-tuple, and then change the composed function back again:
let uncurry3 = \f (x,y,z) -> f x y z curry3 = \f x y z -> f (x,y,z) in curry3 $ f3 . f2 . uncurry3 f1
In your earlier example, this would have been: curry $ sum . uncurry (zipWith (*))
As a side note, this is essentially how all higher order functions are handled in category theory (well, in cartesian closed categories.)
participants (5)
-
Andrew Coppin
-
Brandon S. Allbery KF8NH
-
Derek Elkins
-
Jonathan Cast
-
Steven Fodstad