Eta reduction in haskell - haskell

I tried for a long time to reduct this function in haskell, I want to express for example:
mySum x y = x + y
mySum x y = (+) x y
mySum x = (+) x
mySum = (+) -- it's Messi's goal!
My function it a little more complex, but I really can't do it, I was looking out here and there, and I know there are some techniques, like modify the right side, and use flip. I tried and I got stuck here:
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f x y = map (uncurry f) (zip x y)
Steps:
zipWith' f x y = map (uncurry f) (zip x y)
zipWith' f x y = flip map (zip x y) (uncurry f)
zipWith' f x y = flip map (zip x y) $ uncurry f
and then I don't know how to continue...
I'm looking for an answer that could explain step by step how to achieve the "Messi's goal", I know is a lot to ask, so I will add as soon as I can a bounty to thank the effort

zipWith' f x y = map (uncurry f) (zip x y)
Rewrite application to composition and eta-reduce:
-- \y -> let g = map (uncurry f); h = zip x in (g . h) y
-- let g = map (uncurry f); h = zip x in g . h
zipWith' f x = map (uncurry f) . zip x
Rewrite infix to prefix:
-- g . h = (.) g h
zipWith' f x = (.) (map (uncurry f)) (zip x)
Rewrite application to composition and eta-reduce:
-- \x -> let g = (.) (map (uncurry f)); h = zip in (g . h) x
-- let g = (.) (map (uncurry f)); h = zip in g . h
zipWith' f = (.) (map (uncurry f)) . zip
Rewrite infix to prefix:
-- g . h = (.) g h
zipWith' f = (.) ((.) (map (uncurry f))) zip
Use flip to move f to the right-hand side:
-- flip f x y = f y x
zipWith' f = flip (.) zip ((.) (map (uncurry f)))
Rewrite application to composition:
-- g (h (i x)) = (g . h . i) x
zipWith' f = flip (.) zip (((.) . map . uncurry) f)
Rewrite application to composition and eta-reduce:
-- \f -> let g = flip (.) zip; h = (.) . map . uncurry in (g . h) f
-- let g = flip (.) zip; h = (.) . map . uncurry in g . h
zipWith' = (flip (.) zip) . ((.) . map . uncurry)
Remove redundant parentheses:
zipWith' = flip (.) zip . (.) . map . uncurry
And simplify to infix if you like:
zipWith' = (. zip) . (.) . map . uncurry
This result isn’t very readable, though.
Often when writing fully point-free code, you want to take advantage of the -> applicative and arrow combinators from Control.Arrow. Rather than trying to write a function like \ f x y -> ..., you can start by grouping the arguments into tuples to make them easier to rearrange and pipe around. In this case I’ll use \ (f, (x, y)) -> ...
\ (f, (x, y)) -> map (uncurry f) (zip x y)
We can eliminate the unpacking of (x, y) by applying uncurry to zip:
\ (f, (x, y)) -> map (uncurry f) (uncurry zip (x, y))
\ (f, xy) -> map (uncurry f) (uncurry zip xy)
Now we have a simple case: applying two functions (uncurry and uncurry zip) to two arguments (f and xy), then combining the results (with map). For this we can use the *** combinator from Control.Arrow, of type:
(***) :: Arrow a => a b c -> a b' c' -> a (b, b') (c, c')
Specialised to functions, that’s:
(***) #(->) :: (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
This just lets us apply a function to each element of a pair. Perfect!
uncurry *** uncurry zip
:: (a -> b -> c, ([x], [y])) -> ((a, b) -> c, [(x, y)])
You can think of uncurry f as combining the elements of a pair using the function f. So here we can combine the results using uncurry map:
uncurry map . (uncurry *** uncurry zip)
:: (a -> b -> c, ([a], [b])) -> [c]
And you can think of curry as turning a function on tuples into a multi-argument function. Here we have two levels of tuples, the outer (f, xy) and the inner (x, y). We can unpack the outer one with curry:
curry $ uncurry map . (uncurry *** uncurry zip)
:: (a -> b -> c) -> ([a], [b]) -> [c]
Now, you can think of fmap f in the -> applicative as “skipping over” the first argument:
fmap #((->) _) :: (a -> b) -> (t -> a) -> t -> b
So we can unpack the second tuple using fmap curry:
fmap curry $ curry $ uncurry map . (uncurry *** uncurry zip)
:: (a -> b -> c) -> [a] -> [b] -> [c]
And we’re done! Or not quite. When writing point-free code, it pays to break things out into many small reusable functions with clearer names, for example:
zipWith' = untuple2 $ combineWith map apply zipped
where
untuple2 = fmap curry . curry
combineWith f g h = uncurry f . (g *** h)
apply = uncurry
zipped = uncurry zip
However, while knowing these techniques is useful, all this is just unproductive trickery that’s easy to get lost in. Most of the time, you should only use point-free style in Haskell when it’s a clear win for readability, and neither of these results is clearer than the simple original version:
zipWith' f x y = map (uncurry f) (zip x y)
Or a partially point-free version:
zipWith' f = map (uncurry f) .: zip
where (.:) = (.) . (.)

Related

Idris `foldl` default implementation

interface Foldable t where
foldr : (func : elem -> acc -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl : (func : acc -> elem -> acc) -> (init : acc) -> (input : t elem) -> acc
foldl f z t = foldr (flip (.) . flip f) id t z
What does foldr (flip (.) . flip f) id t z mean here?
And is there another way to implement foldl using foldr?
Thanks for answering.
The first argument in the foldl defined above could be turned into a lambda like this:
\element -> (. (flip f element))
-- or
\element prevFun -> prevFun . flip f element
-- or
\element prevFun next -> prevFun $ f next element
Let's take an example where you want to fold left over a list [a, b, c]. You want your end result to be f (f (f z a) b) c), where z is the accumulator.
In the first iteration, the first argument would be c and the second id. Thus, the result would be id . flip f c, or just flip f c (since id . f is simply f, as #chepner pointed out).
The second iteration would result in flip f c . flip f b, and after that you would get flip f c . flip f b . flip f a (basically, adding a . flip f x for every next element x.
This expands to:
acc -> flip f c (flip f b (flip f a acc))
-- or
acc -> flip f c (flip f b (f acc a))
-- or
acc -> f (f (f acc a) b) c)
Et voila! We have a function that takes an accumulator acc, and returns the result of foldl f acc t, so we simply apply that to z, the actual accumulator.

How to implement uncurry point-free in Haskell without app?

I have been wondering how different standard Haskell functions could be implemented point-free. Currently, I am interested in uncurry and I feel this one is quite non-trivial.
The main problem is that we are unable (or as it seems to me) to group the arguments. If we had uncurry (in fact, uncurry ($) would suffice) in use, the solution would have been quite simple:
Make a tuple (f, (x, y)).
Apply assoc1 :: (a, (b, c)) -> ((a, b), c) to the tuple and get ((f, x), y).
Apply the uncurried ($) to the first element of the pair and get (f x, y).
Apply the uncurried ($) to the pair itself and get f x y.
Without the uncurried ($) we would have to extract both elements of the pair separately. E.g.:
uncurry f pair = f (fst pair) (snd pair)
I do not reckon this to be a smooth way to implement something point-free.
In fact, we have got this uncurried ($) at our behest: Control.Arrow.apply (other useful for the solution combinators could also be imported from Control.Arrow). Therefore:
import Control.Arrow ((>>>), (&&&), first, app)
myUncurry = let myAssoc1 = (fst &&& (fst . snd)) &&& (snd . snd)
in (,) >>> (>>> myAssoc1 >>> first app >>> app)
Yet, this feels a small bit like cheating.
Are there any other approaches towards this problem which do not require anything like app?
join on functions gives you (a -> a -> b) -> a -> b, so:
myUncurry f = join (\x y -> f (fst x) (snd y))
myUncurry f = join (\x -> f (fst x) . snd)
myUncurry f = join ((.snd) . f . fst)
myUncurry f = join ((.fst) ((.snd) . f))
myUncurry f = join ((.fst) ((.) (.snd) f))
myUncurry = join . (.fst) . \f -> (.) (.snd) f
myUncurry = join . (.fst) . ((.snd).)
join . (.fst) . ((.snd).) is very readable indeed
The artless, mechanical solution, by "pushing lambdas inward".
uncurry f (x,y) = f x y
uncurry f p = f (fst p) (snd p)
uncurry f = \p -> f (fst p) (snd p)
uncurry f = (<*>) (\p -> f (fst p)) (\p -> snd p)
uncurry f = (<*>) (f . fst) snd
uncurry = \f -> (<*>) (f . fst) snd
uncurry = flip (\f -> (<*>) (f . fst)) snd
uncurry = flip ((<*>) . (\f -> f . fst)) snd
uncurry = flip ((<*>) . (. fst)) snd
With Lambda Calculus' S combinator, Sabc = (a <*> b) c = a c $ b c,
uncurry f (x,y) = f (fst (x,y)) (snd (x,y))
= (f . fst <*> snd) (x,y)
uncurry f = (<*> snd) (f . fst)
= (<*> snd) . (. fst) $ f
hence,
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry = (<*> snd) . (. fst)
(edit:)
Still it's much more readable (and somewhat elucidating) with one explicit argument left there, as seen above:
uncurry f = f . fst <*> snd
But then this variant, shown by Jon Purdy in the comments,
uncurry f = liftA2 f fst snd
just might be the clearest.
This is because for functions, the monad and the applicative are equivalent in power,
(k =<< f) x = k (f x) x = flip k x (f x) = (flip k <*> f) x
-- i.e., uncurry f = flip (f . fst) =<< snd
and liftA2 f fst snd means, by definition,
= [ f a b | a <- fst ; b <- snd ]
=
do { a <- fst ;
b <- snd ;
return (f a b)
}
= \x -> let
{ a = fst x ;
b = snd x ;
}
in const (f a b) x
(the first one written with Monad Comprehensions). Thus,
uncurry f x = liftA2 f fst snd x
= let
{ a = fst x ;
b = snd x ;
}
in f a b
=
f (fst x) (snd x)
=
(f . fst <*> snd) x
=
(flip (f . fst) =<< snd) x
=
flip (f . fst) (snd x) x
=
(flip (f . fst) . snd) x x
=
join (flip (f . fst) . snd) x
=
join (flip (f . fst) <$> snd) x
following the well known equivalence, k =<< m = join (fmap k m) (and for functions, (<$>) = fmap = (.)).
So we've found yet another expression here,
uncurry f x = join (flip (f . fst) . snd)
= liftA2 f fst snd
= f . fst <*> snd
= flip (f . fst) =<< snd
The liftA2 one just might be the clearest and the least noisy.

How can two continuations cancel each other out?

I'm reading through Some Tricks for List Manipulation, and it contains the following:
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (\((y:ys),r) -> c (ys,(x,y):r))
What we can see here is that we have two continuations stacked on top
of each other. When this happens, they can often “cancel out”, like
so:
zipRev xs ys = snd (foldr f (ys,[]) xs)
where
f x (y:ys,r) = (ys,(x,y):r)
I don't understand how you "cancel out" stacked continuations to get from the top code block to the bottom one. What pattern do you look for to make this transformation, and why does it work?
A function f :: a -> b can be "disguised" inside double continuations as a function f' :: ((a -> r1) -> r2) -> ((b -> r1) -> r2).
obfuscate :: (a -> b) -> ((a -> r1) -> r2) -> (b -> r1) -> r2
obfuscate f k2 k1 = k2 (k1 . f)
obfuscate has the nice property that it preserves function composition and identity: you can prove that obfuscate f . obfuscate g === obfuscate (f . g) and that obfuscate id === id in a few steps. That means that you can frequently use this transformation to untangle double-continuation computations that compose obfuscated functions together by factoring the obfuscate out of the composition. This question is an example of such an untangling.
The f in the top code block is the obfuscated version of the f in the bottom block (more precisely, top f x is the obfuscated version of bottom f x). You can see this by noticing how top f applies the outer continuation to a function that transforms its input and then applies the whole thing to the inner continuation, just like in the body of obfuscate.
So we can start to untangle zipRev:
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x = obfuscate (\(y:ys,r) -> (ys,(x,y):r))
Since the action of foldr here is to compose a bunch of obfuscated functions with each other (and apply it all to id, which we can leave on the right), we can factor the obfuscate to the outside of the whole fold:
zipRev xs ys = obfuscate (\accum -> foldr f accum xs) id snd (ys,[])
where
f x (y:ys,r) = (ys,(x,y):r)
Now apply the definition of obfuscate and simplify:
zipRev xs ys = obfuscate (\accum -> foldr f accum xs) id snd (ys,[])
zipRev xs ys = id (snd . (\accum -> foldr f accum xs)) (ys,[])
zipRev xs ys = snd (foldr f (ys,[]) xs)
QED!
Given a function
g :: a₁ -> a₂
we can lift it to a function on continuations, switching the order:
lift g = (\c a₁ -> c (g a₁))
:: (a₂ -> t) -> a₁ -> t
This transformation is a contravariant functor, which is to say that it interacts with function composition by switching its order:
g₁ :: a₁ -> a₂
g₂ :: a₂ -> a₃
lift g₁ . lift g₂
== (\c₁ a₁ -> c₁ (g₁ a₁)) . (\c₂ a₂ -> c₂ (g₂ a₂))
== \c₂ a₁ -> (\a₂ -> c₂ (g₂ a₂)) (g₁ a₁)
== \c₂ a₁ -> c₂ (g₂ (g₁ a₁))
== lift (g₂ . g₁)
:: (a₃ -> t) -> a₁ -> t
lift id
== (\c a₁ -> c a₁)
== id
:: (a₁ -> t) -> a₁ -> t
We can lift the lifted function again in the same way to a function on stacked continuations, with the order switched back:
lift (lift g)
== (\k c -> k ((\c a₁ -> c (g a₁)) c))
== (\k c -> k (\a₁ -> c (g a₁)))
:: ((a₁ -> t) -> u) -> (a₂ -> t) -> u
Stacking two contravariant functors gives us a (covariant) functor:
lift (lift g₁) . lift (lift g₂)
== lift (lift g₂ . lift g₁)
== lift (lift (g₁ . g₂))
:: ((a₁ -> t) -> u) -> (a₃ -> t) -> u
lift (lift id)
== lift id
== id
:: ((a₁ -> t) -> u) -> (a₁ -> t) -> u
This is exactly the transformation being reversed in your example, with g = \(y:ys, r) -> (ys, (x, y):r). This g is an endomorphism (a₁ = a₂), and the foldr is composing together a bunch of copies of it with various x. What we’re doing is replacing the composition of double-lifted functions with the double-lift of the composition of the functions, which is just an inductive application of the functor laws:
f :: x -> a₁ -> a₁
c :: (a₁ -> t) -> u
xs :: [x]
foldr (\x -> lift (lift (f x))) c xs
== lift (lift (\a₁ -> foldr f a₁ xs)) c
:: (a₁ -> t) -> u
Let's try to understand this code from an elementary point of view. What does it even do, one wonders?
zipRev xs ys = foldr f id xs snd (ys,[])
where
-- f x k c = k (\(y:ys, r) -> c (ys, (x,y):r))
f x k c = k (g x c)
-- = (k . g x) c -- so,
-- f x k = k . g x
g x c (y:ys, r) = c (ys, (x,y):r)
Here we used lambda lifting to recover the g combinator.
So then because f x k = k . g x were k goes to the left of x, the input list is translated into a reversed chain of compositions,
foldr f id [x1, x2, x3, ..., xn] where f x k = k . g x
===>>
(((...(id . g xn) . ... . g x3) . g x2) . g x1)
and thus, it just does what a left fold would do,
zipRev [] ys = []
zipRev [x1, x2, x3, ..., xn] ys
= (id . g xn . ... . g x3 . g x2 . g x1) snd (ys, [])
= g xn (g xn1 ( ... ( g x3 ( g x2 ( g x1 snd)))...)) (ys, [])
where ----c--------------------------------------------
g x c (y:ys, r) = c (ys, (x,y):r)
So we went to the deep end of the xs list, and then we come back consuming the ys list left-to-right (i.e. top-down) on our way back right-to-left on the xs list (i.e. bottom-up). This is straightforwardly coded as a right fold with strict reducer, so the flow is indeed right-to-left on the xs. The bottom-most action (snd) in the chain is done last, so in the new code it becomes the topmost (still done last):
zipRev xs ys = snd (foldr h (ys,[]) xs)
where
h x (y:ys, r) = (ys, (x,y):r)
g x c was used as a continuation in the original code, with c as a second-tier continuation; but it's actually all just been a regular fold from the right, all along.
So indeed it zips the reversed first list with the second. It's also unsafe; it misses a clause:
g x c ([], r) = c ([], r) -- or just `r`
g x c (y:ys, r) = c (ys, (x,y):r)
(update:) The answers by duplode (and Joseph Sible) do the lambda lifting a bit differently, in a way which is better suited to the task. It goes like this:
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (\((y:ys), r) -> c (ys, (x,y):r))
= k (c . (\((y:ys), r) -> (ys, (x,y):r)) )
= k (c . g x)
g x = (\((y:ys), r) -> (ys, (x,y):r))
{- f x k c = k ((. g x) c) = (k . (. g x)) c = (. (. g x)) k c
f x = (. (. g x)) -}
so then
foldr f id [ x1, x2, ... , xn ] snd (ys,[]) =
= ( (. (. g x1)) $ (. (. g x2)) $ ... $ (. (. g xn)) id ) snd (ys,[]) -- 1,2...n
= ( id . (. g xn) . ... . (. g x2) . (. g x1) ) snd (ys,[]) -- n...2,1
= ( snd . g x1 . g x2 . ... . g xn ) (ys,[]) -- 1,2...n!
= snd $ g x1 $ g x2 $ ... $ g xn (ys,[])
= snd $ foldr g (ys,[]) [x1, x2, ..., xn ]
Simple. :) Flipping twice is no flipping at all.
Let's begin with a few cosmetic adjustments:
-- Note that `g x` is an endomorphism.
g :: a -> ([b], [(a,b)]) -> ([b], [(a,b)])
g x ((y:ys),r) = (ys,(x,y):r)
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k = \c -> k (c . g x)
f feeds a continuation (c . g x) to another function (k, a "double continuation", as user11228628 puts it).
While we might reasonably expect that repeated usage of f as the fold proceeds will somehow compose the g x endomorphisms made out of the elements of the list, the order in which the endomorphisms are composed might not be immediately obvious, so we'd better walk through a few fold steps to be sure:
-- x0 is the first element, x1 the second, etc.
f x0 k0
\c -> k0 (c . g x0)
\c -> (f x1 k1) (c . g x0) -- k0 is the result of a fold step.
\c -> (\d -> k1 (d . g x1)) (c . g x0) -- Renaming a variable for clarity.
\c -> k1 (c . g x0 . g x1)
-- etc .
-- xa is the *last* element, xb the next-to-last, etc.
-- ka is the initial value passed to foldr.
\c -> (f xa ka) (c . g x0 . g x1 . . . g xb)
\c -> (\d -> ka (d . g xa)) (c . g x0 . g x1 . . . g xb)
\c -> ka (c . g x0 . g x1 . . . g xb . g xa)
ka, the initial value passed to foldr, is id, which makes things quite a bit simpler:
foldr f id xs = \c -> c . g x0 . g x1 . . . g xa
Since all we do with the c argument passed to foldr f id xs is post-composing it with the endomorphisms, we might as well factor it out of the fold:
zipRev xs ys = (snd . foldr h id xs) (ys,[])
where
h x e = g x . e
Note how we have gone from c . g x to g x . e. That can arguably be described as a collateral effect of the CPS trickery in the original implementation.
The final step is noticing how h x e = g x . e corresponds exactly to what we would do to implement foldr in terms of foldMap for the Endo monoid. Or, to put it more explicitly:
foldEndo g i xs = foldr g i xs -- The goal is obtaining an Endo-like definition.
foldEndo _ i [] = i
foldEndo g i (x : xs) = g x (foldEndo g i xs)
foldEndo g i xs = go xs i
where
go [] = \j -> j
go (x : xs) = \j -> g x (foldEndo g j xs)
foldEndo g i xs = go xs i
where
go [] = \j -> j
go (x : xs) = \j -> g x (go xs j)
foldEndo g i xs = go xs i
where
go [] = id
go (x : xs) = g x . go xs
foldEndo g i xs = go xs i
where
h x e = g x . e
go [] = id
go (x : xs) = h x (go xs)
foldEndo g i xs = go xs i
where
h x e = g x . e
go xs = foldr h id xs
foldEndo g i xs = foldr h id xs i
where
h x e = g x . e
That finally leads us to what we were looking for:
zipRev xs ys = snd (foldr g (ys,[]) xs)
user11228628's answer led me to understanding. Here's a few insights I had while reading it, and some step-by-step transformations.
Insights
The continuations don't directly cancel out. They can only eventually be canceled (by beta-reducing) because it's possible to factor them out.
The pattern you're looking for to do this transformation is \k c -> k (c . f) (or if you love unreadable pointfree, (. (. f))) for any f (note that the f isn't a parameter to the lambda).
As duplode points out in a comment, continuation-passing style functions can be considered a functor, and obfuscate is their definition of fmap.
The trick of pulling a function like this out of foldr works for any function that could be a valid fmap.
Full transformation from the first code block to the second
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (\((y:ys),r) -> c (ys,(x,y):r))
Pull c out of the lambda
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x k c = k (c . \((y:ys),r) -> (ys,(x,y):r))
Substitute obfuscate for its definition
zipRev xs ys = foldr f id xs snd (ys,[])
where
f x = obfuscate (\((y:ys),r) -> (ys,(x,y):r))
Pull obfuscate out of the lambda
zipRev xs ys = foldr f id xs snd (ys,[])
where
f = obfuscate . \x ((y:ys),r) -> (ys,(x,y):r)
Pull obfuscate out of f
zipRev xs ys = foldr (obfuscate . f) id xs snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Since obfuscate follows the Functor laws, we can pull it out of foldr
zipRev xs ys = obfuscate (flip (foldr f) xs) id snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Inline obfuscate
zipRev xs ys = (\k c -> k (c . flip (foldr f) xs)) id snd (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Beta-reduce
zipRev xs ys = (id (snd . flip (foldr f) xs)) (ys,[])
where
f x ((y:ys),r) = (ys,(x,y):r)
Simplify
zipRev xs ys = snd (foldr f (ys,[]) xs)
where
f x (y:ys,r) = (ys,(x,y):r)
Justification for pulling functions that are valid fmaps out of foldr
foldr (fmap . f) z [x1,x2,...,xn]
Expand the foldr
(fmap . f) x1 . (fmap . f) x2 . ... . (fmap . f) xn $ z
Inline the inner .s
fmap (f x1) . fmap (f x2) . ... . fmap (f xn) $ z
Apply the Functor laws
fmap (f x1 . f x2 . ... . f xn) $ z
Eta-expand the section in parentheses
fmap (\z2 -> f x1 . f x2 . ... . f xn $ z2) z
Write the lambda body in terms of foldr
fmap (\z2 -> foldr f z2 [x1,x2,...,xn]) z
Write the lambda body in terms of flip
fmap (flip (foldr f) [x1,x2,...,xn]) z
Bonus: Justification for pulling functions that are valid contramaps out of foldr
foldr (contramap . f) z [x1,x2,...,xn]
Expand the foldr
(contramap . f) x1 . (contramap . f) x2 . ... . (contramap . f) xn $ z
Inline the inner .s
contramap (f x1) . contramap (f x2) . ... . contramap (f xn) $ z
Apply the Contravariant laws
contramap (f xn . ... . f x2 . f x1) $ z
Eta-expand the section in parentheses
contramap (\z2 -> f xn . ... . f x2 . f x1 $ z2) z
Write the lambda body in terms of foldr
contramap (\z2 -> foldr f z2 [xn,...,x2,x1]) z
Write the lambda body in terms of flip
contramap (flip (foldr f) [xn,...,x2,x1]) z
Apply foldr f z (reverse xs) = foldl (flip f) z xs
contramap (flip (foldl (flip f)) [x1,x2,...,xn]) z

($) is to (.) as `fmap` is to?

I have a function funcM :: a -> b -> c -> IO (x, y)
I want to write a function funcM_ :: a-> b-> c-> IO x so:
funcM_ = fst `fmap` funcM -- error
I could add back all the points, but it seems like there should be something I could replace fmap with so that the above will work. Kind of like replacing ($) with (.) would make this work in a pure context.
What is the function I am looking for?
Since you’re composing a one-argument function (fmap) with a three-argument function (funcM), you need three levels of composition:
funcM_ = ((fmap fst .) .) . funcM
This is equivalent to the pointed version by a simple expansion:
funcM_ x = (fmap fst .) . funcM x
funcM_ x y = fmap fst . funcM x y
funcM_ x y z = fmap fst (funcM x y z)
This follows from the type of fmap, really:
fmap :: (Functor f) => (a -> b) -> f a -> f b
You’re just partially applying the arguments to funcM so that you have an f a (here IO (x, y)) which you give to fmap fst to get back an f b (IO x).
As an aside, M_ usually implies returning m ().
Take a look at the following answer: https://stackoverflow.com/a/20279307/783743 It explains how to convert your code into pointfree style. Let's start with a non-pointfree definition of funcM_:
funcM_ a b c = fmap fst (funcM a b c)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ a b = fmap fst . (funcM a b)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ a = (fmap fst .) . (funcM a)
-- But `\x -> f (g x)` is `f . g`. Hence:
funcM_ = ((fmap fst .) .) . funcM
Another way to do this would be to use uncurry and curry as follows:
uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 f (a, b, c) = f a b c
curry3 :: ((a, b, c) -> d) -> a -> b -> c -> d
curry3 f a b c = f (a, b, c)
(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
f .:: g = curry3 (f . (uncurry3 g))
Now you can write funcM_ as follows:
funcM_ = fmap fst .:: funcM
You could also write .:: in pointfree style as follows:
(.::) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
(.::) = (.) . (.) . (.)
Hope that helped.
Add a dot for each argument to funcM
These are all equivalent:
((fmap fst . ) .) . funcM
((.) . (.) . (.)) (fmap fst) funcM
(fmap . fmap . fmap) (fmap fst) funcM
import Data.Functor.Syntax -- from 'functors' package
(.::) (fmap fst) funcM
Note that all I did was change the implicit ($) to (.).
:-)
(.) is the implementation of fmap for the function instance of Functor :
instance Functor ((->) a) b where
fmap f g = f . g
GHCi :t is your friend.

What does (f .) . g mean in Haskell?

I have seen a lot of functions being defined according to the pattern (f .) . g. For example:
countWhere = (length .) . filter
duplicate = (concat .) . replicate
concatMap = (concat .) . map
What does this mean?
The dot operator (i.e. (.)) is the function composition operator. It is defined as follows:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
As you can see it takes a function of type b -> c and another function of type a -> b and returns a function of type a -> c (i.e. which applies the first function to the result of the second function).
The function composition operator is very useful. It allows you to pipe the output of one function into the input of another function. For example you could write a tac program in Haskell as follows:
main = interact (\x -> unlines (reverse (lines x)))
Not very readable. Using function composition however you could write it as follows:
main = interact (unlines . reverse . lines)
As you can see function composition is very useful but you can't use it everywhere. For example you can't pipe the output of filter into length using function composition:
countWhere = length . filter -- this is not allowed
The reason this is not allowed is because filter is of type (a -> Bool) -> [a] -> [a]. Comparing it with a -> b we find that a is of type (a -> Bool) and b is of type [a] -> [a]. This results in a type mismatch because Haskell expects length to be of type b -> c (i.e. ([a] -> [a]) -> c). However it's actually of type [a] -> Int.
The solution is pretty simple:
countWhere f = length . filter f
However some people don't like that extra dangling f. They prefer to write countWhere in pointfree style as follows:
countWhere = (length .) . filter
How do they get this? Consider:
countWhere f xs = length (filter f xs)
-- But `f x y` is `(f x) y`. Hence:
countWhere f xs = length ((filter f) xs)
-- But `\x -> f (g x)` is `f . g`. Hence:
countWhere f = length . (filter f)
-- But `f . g` is `(f .) g`. Hence:
countWhere f = (length .) (filter f)
-- But `\x -> f (g x)` is `f . g`. Hence:
countWhere = (length .) . filter
As you can see (f .) . g is simply \x y -> f (g x y). This concept can actually be iterated:
f . g --> \x -> f (g x)
(f .) . g --> \x y -> f (g x y)
((f .) .) . g --> \x y z -> f (g x y z)
(((f .) .) .) . g --> \w x y z -> f (g w x y z)
It's not pretty but it gets the job done. Given two functions you can also write your own function composition operators:
f .: g = (f .) . g
f .:: g = ((f .) .) . g
f .::: g = (((f .) .) .) . g
Using the (.:) operator you could write countWhere as follows instead:
countWhere = length .: filter
Interestingly though you could write (.:) in point free style as well:
f .: g = (f .) . g
-- But `f . g` is `(.) f g`. Hence:
f .: g = (.) (f .) g
-- But `\x -> f x` is `f`. Hence:
(f .:) = (.) (f .)
-- But `(f .)` is `((.) f)`. Hence:
(f .:) = (.) ((.) f)
-- But `\x -> f (g x)` is `f . g`. Hence:
(.:) = (.) . (.)
Similarly we get:
(.::) = (.) . (.) . (.)
(.:::) = (.) . (.) . (.) . (.)
As you can see (.:), (.::) and (.:::) are just powers of (.) (i.e. they are iterated functions of (.)). For numbers in Mathematics:
x ^ 0 = 1
x ^ n = x * x ^ (n - 1)
Similarly for functions in Mathematics:
f .^ 0 = id
f .^ n = f . (f .^ (n - 1))
If f is (.) then:
(.) .^ 1 = (.)
(.) .^ 2 = (.:)
(.) .^ 3 = (.::)
(.) .^ 4 = (.:::)
That brings us close to the end of this article. For a final challenge let's write the following function in pointfree style:
mf a b c = filter a (map b c)
mf a b c = filter a ((map b) c)
mf a b = filter a . (map b)
mf a b = (filter a .) (map b)
mf a = (filter a .) . map
mf a = (. map) (filter a .)
mf a = (. map) ((filter a) .)
mf a = (. map) ((.) (filter a))
mf a = ((. map) . (.)) (filter a)
mf = ((. map) . (.)) . filter
mf = (. map) . (.) . filter
We can further simplify this as follows:
compose f g = (. f) . (.) . g
compose f g = ((. f) . (.)) . g
compose f g = (.) ((. f) . (.)) g
compose f = (.) ((. f) . (.))
compose f = (.) ((. (.)) (. f))
compose f = ((.) . (. (.))) (. f)
compose f = ((.) . (. (.))) (flip (.) f)
compose f = ((.) . (. (.))) ((flip (.)) f)
compose = ((.) . (. (.))) . (flip (.))
Using compose you can now write mf as:
mf = compose map filter
Yes it is a bit ugly but it's also a really awesome mind-boggling concept. You can now write any function of the form \x y z -> f x (g y z) as compose f g and that is very neat.
This is a matter of taste, but I find such style to be unpleasant. First I'll describe what it means, and then I suggest an alternative that I prefer.
You need to know that (f . g) x = f (g x) and (f ?) x = f ? x for any operator ?. From this we can deduce that
countWhere p = ((length .) . filter) p
= (length .) (filter p)
= length . filter p
so
countWhere p xs = length (filter p xs)
I prefer to use a function called .:
(.:) :: (r -> z) -> (a -> b -> r) -> a -> b -> z
(f .: g) x y = f (g x y)
Then countWhere = length .: filter. Personally I find this a lot clearer.
(.: is defined in Data.Composition and probably other places too.)

Resources