[Haskell-beginners] A little explanation! follow up

Brent Yorgey byorgey at seas.upenn.edu
Wed Apr 30 18:15:57 UTC 2014


On Wed, Apr 30, 2014 at 11:25:58AM -0600, Dimitri DeFigueiredo wrote:
> I have a follow up question on this one. Is code like this:
> 
> elementAt_w'pf = (last .) . take . (+ 1)
> 
> considered good haskell?

Uses of composition sections like (last .) is not very common; I would
not consider it good haskell (though tastes may differ).  On the other
hand, point-free notation, used in moderation, is considered good
Haskell style. For example, instead of

  foo x = bar (baz (quux x))

you should write

  foo = bar . baz . quux

In this case I would certainly consider the second definition better
style than the first.

> If so, will this ever become easy to read?
> What do I do to practice reading this?

Just read and write lots of code.  Try transforming things into and
out of point-free notation as an exercise.

> More specifically, how would I know in mind head, before asking the
> type checker in GHCi to write this pipeline with the section (last .)
> instead of simply making the (wrong) pipe:
> 
> elementAt_w'pf = last . take . (+ 1)

Simply by working out the types in your head.  This becomes much
easier with practice.

> I am used to using pipes in the unix shell, but in the shell there is
> always only one input and one output. There is no currying going on
> and so it is very clear what we are dealing with. How do I learn
> this?

There is always only one input and one output in Haskell as well.  The
thing that makes it more complicated is that unlike in the shell,
those inputs and outputs can themselves be functions.

-Brent

> 
> 
> Em 30/04/14 09:53, Kyle Murphy escreveu:
> >Near as I can tell, this is basically having to do with partial
> >application and the order of precedence for the (.) operator. A
> >great way to look at this stuff is using the :t command in GHCi and
> >checking out the types involved.
> >
> >Prelude> :t (.)
> >(.) :: (b -> c) -> (a -> b) -> a -> c
> >
> >Prelude> :t last
> >last :: [a] -> a
> >
> >Prelude> :t (last .)
> >(last .) :: (a -> [c]) -> a -> c
> >
> >Looking back at the type for (.) and plugging in "[a]" in place of
> >"b" and "a" in place of "c" we get:
> >([b] -> b) -> (a -> [b]) -> a -> b
> >
> >and since "last" takes the place of the first function we can
> >reduce that to:
> >(a -> [b]) -> a -> b
> >
> >GHCi used "c" where we used "b" but you can clearly see the
> >signatures are identical other than that detail.
> >
> >What we're left with is, (last .) is used to take a function from
> >some type "a" that returns a list of type "b", and a "a" value, and
> >then returns the last value from that list of "b" types.
> >
> >
> >-R. Kyle Murphy
> >--
> >Curiosity was framed, Ignorance killed the cat.
> >
> >
> >On Wed, Apr 30, 2014 at 11:29 AM, Gilberto Melfe
> ><gilbertomelfe at gmail.com <mailto:gilbertomelfe at gmail.com>> wrote:
> >
> >    Hello everybody !
> >
> >    Could someone explain me exactly how this function works?
> >
> >    elementAt_w'pf = (last .) . take . (+ 1)
> >
> >    It's a posted solution to: 99 Haskell problems, problem 3.
> >
> >    I'm having trouble with the "(last .) ." thing!
> >
> >    Hope someone can help!
> >
> >    Thank You!
> >
> >    Gilberto
> >
> >    _______________________________________________
> >    Beginners mailing list
> >    Beginners at haskell.org <mailto:Beginners at haskell.org>
> >    http://www.haskell.org/mailman/listinfo/beginners
> >
> >
> >
> >
> >_______________________________________________
> >Beginners mailing list
> >Beginners at haskell.org
> >http://www.haskell.org/mailman/listinfo/beginners
> 
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners


More information about the Beginners mailing list