[Haskell-beginners] Are these soloutions all valid and a good use of Haskell

Stefan Höck efasckenoth at gmail.com
Mon Nov 10 14:23:31 UTC 2014


Just a quick note: That's 'typed holes' not 'type holes' ...

On Mon, Nov 10, 2014 at 03:12:20PM +0100, Stefan Höck wrote:
> Hi Roelof
> 
> It seems like you try to do too many things at once. Here's how you
> could go about this step-by-step and let GHC help you implement your
> functions along the way:
> 
> First, give the type signature of your function:
> 
>   last5 :: [a] -> Maybe a
>   last5 = undefined
> 
> Now, load this into GHCi or compile with GHC. If it compiles, you're
> on the right track. Now, you want to implement it using a fold
> (try both, foldl and foldr):
> 
>   last5 :: [a] -> Maybe a
>   last5 xs = foldr _ _ xs
> 
> The underscores are 'type holes'. This tells the compiler to give you
> some information about what is supposed to be placed at the two
> positions. For the moment, we are only interested in the types of the
> things that go there. The compiler will tell you, that
> the hole at the first position is of type
> 
>   a -> Maybe a -> Maybe a
> 
> and the hole at the second position is of type
> 
>   Maybe a
> 
> Now, instead of filling the holes in place, let's define two helper
> functions together with their type signatures. You can later on inline
> them in your definition of last5, but for the time being, let's get as
> much help from the compiler as we can.
> 
>   last5 :: [a] -> Maybe a
>   last5 xs = foldr acc initial xs
> 
>   acc :: a -> Maybe a -> Maybe a
>   acc = undefined
> 
>   initial :: Maybe a
>   initial = undefined
> 
> Again, compile or load into GHCi. If you did anything wrong, the 
> compiler will tell you so. There is only one possible way to
> implement function `initial` without cheating (= raising an error)
> 
>   initial :: Maybe a
>   initial = Nothing
> 
> Function `acc` can be implemented in several ways. Only one of them
> will lead to the desired behavior. Finding out the proper implementation
> is the main point of this folding-exercise. Try also an implementation
> using foldl. Does it behave as expected? What are the differences
> compared to foldr?  When you feed your implementations a huge list -
> say [1..20000000] - what happens?
> 
> Note that whenever you get an error message in a rather complex
> function implementation, move local function definitions and lambdas
> to the top level, give them a type signature and implement them
> separately one at a time. Use type holes to let the compiler give
> assistance with type signatures and possible implementations.
> Once everything compiles and runs as expected, move the toplevel
> definitions back to where you'd like them best.
> 
> Stefan
> 
> PS: A more succint implementation of last5 would use currying:
> 
>     last5 = foldr acc initial
> 
> PPS: If you get a stack overflow with very large lists, try
>      using foldl' from Data.List (or better, once you learned
>      about the Foldable type class, from Data.Foldable).
> 
> On Mon, Nov 10, 2014 at 02:28:08PM +0100, Roelof Wobben wrote:
> > I tried and so far I have this :
> > 
> > last5 = foldl(\acc x -> if x=[] then x else acc xs) [] xs
> > 
> > But now I get parse error on the -> part.
> > 
> > Roelof
> > 
> > 
> > Roelof Wobben schreef op 10-11-2014 13:47:
> > >Thanks all,
> > >
> > >I will try to make a fold solution as soon as I see that functional
> > >explained in the learnyouahaskell.
> > >
> > >Roelof
> > >
> > >
> > >Frerich Raabe schreef op 10-11-2014 11:43:
> > >>On 2014-11-10 11:16, Karl Voelker wrote:
> > >>>On Mon, Nov 10, 2014, at 01:50 AM, Roelof Wobben wrote:
> > >>>>What do you experts think of the different ways ?
> > >>>
> > >>>2 and 4 are quite similar, and both fine. 3 is not so good: guards
> > >>>provide weaker guarantees than patterns, and head and tail are partial
> > >>>functions.
> > >>
> > >>In addition to what Karl wrote, I'd like to suggest not using the
> > >>semicolon all the time -- it's not needed and just adds noise.
> > >>
> > >>>All three implementations have in common that they do their own
> > >>>recursion. It would be a good exercise to try implementing last as a
> > >>>fold - in other words, letting the standard library do the recursion
> > >>>for
> > >>>you.
> > >>
> > >>Right - I suggest trying to express the problem with the most abstract
> > >>function first, then consider using a fold, then use manual recursion.
> > >>in
> > >>your particular case you could exploit that for non-empty lists, getting
> > >>the last element of a list is the same as getting the first element of
> > >>a reversed list (and there are ready-made functions for reversing a list
> > >>and getting the first element of a list).
> > >>
> > >
> > >_______________________________________________
> > >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