
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr. init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar" This is as far as I got: init xs = foldr left [] xs left :: a -> [a] -> [a] left x [] = [] left x1 : (x2 : xs) = x1 : (left x2 xs) But this returns [] and doesn't work. I can't get "left" to know that it is working with the rightmost element. It just throws away every element when its right hand side is empty. I found a solution that works for Strings, but I am looking for a more general solution. This exercise may yet again be one of those that is difficult to solve with my current knowledge of Haskell, but I'm asking anyway. -- Kaoru Hosokawa khosokawa@gmail.com

On Sun, 2005-04-10 at 15:44 +0900, Kaoru Hosokawa wrote:
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
Hi, Here's a tentative solution: myinit xs = foldr (f (length xs)) [] xs where f len next [] | len == 1 = [] | otherwise = [next] f len next list@(x:xs) | length list + 1 == len = next : xs | otherwise = x : next : xs What's the algorithm? We want to float the last item in the list to the front, and then drop it off when the whole list is processed. The trick is in knowing when we've processed the entire list. That is done by keeping track of the length of the original input list, and comparing that with the number of items processed. There is a special case when the original list has only one element in it. Not very efficient though! Also it behaves differently than init for the empty list. Perhaps you can come up with a more efficient solution! Cheers, Bernie.

My solution based on Bernie's solution: init :: [a] -> [a] init xs = foldr (left (length xs)) xs xs left :: Int -> a -> [a] -> [a] left n x xs | n == length xs = [] | otherwise = x : xs I use the foldr return value for the empty list as the input itself. Use this value as a marker to signify that I am at the end of the list by checking its length. On 2005/04/10, at 17:13, Bernard Pope wrote:
On Sun, 2005-04-10 at 15:44 +0900, Kaoru Hosokawa wrote:
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
Hi,
Here's a tentative solution:
myinit xs = foldr (f (length xs)) [] xs where f len next [] | len == 1 = [] | otherwise = [next] f len next list@(x:xs) | length list + 1 == len = next : xs | otherwise = x : next : xs
-- Kaoru Hosokawa khosokawa@gmail.com

At 10:50 AM +0900 2005/4/16, Kaoru Hosokawa wrote:
My solution based on Bernie's solution:
init :: [a] -> [a] init xs = foldr (left (length xs)) xs xs
left :: Int -> a -> [a] -> [a] left n x xs | n == length xs = [] | otherwise = x : xs
I use the foldr return value for the empty list as the input itself. Use this value as a marker to signify that I am at the end of the list by checking its length.
Using length causes this definition of init to fail on infinite lists. --Ham -- ------------------------------------------------------------------ Hamilton Richards, PhD Department of Computer Sciences Senior Lecturer The University of Texas at Austin 512-471-9525 1 University Station C0500 Taylor Hall 5.138 Austin, Texas 78712-0233 ham@cs.utexas.edu hrichrds@swbell.net http://www.cs.utexas.edu/users/ham/richards ------------------------------------------------------------------

On 2005/04/16, at 12:57, Hamilton Richards wrote:
At 10:50 AM +0900 2005/4/16, Kaoru Hosokawa wrote:
My solution based on Bernie's solution:
init :: [a] -> [a] init xs = foldr (left (length xs)) xs xs
left :: Int -> a -> [a] -> [a] left n x xs | n == length xs = [] | otherwise = x : xs
I use the foldr return value for the empty list as the input itself. Use this value as a marker to signify that I am at the end of the list by checking its length.
Using length causes this definition of init to fail on infinite lists.
Oh. I haven't learned how to handle infinite data structures yet, but is init defined for infinite lists in the first place? -- Kaoru Hosokawa khosokawa@gmail.com

Oh. I haven't learned how to handle infinite data structures yet, but is init defined for infinite lists in the first place?
-- Kaoru Hosokawa khosokawa@gmail.com
Yes it is, try "init [1..]" in ghci or hugs. It just happens to be the identity function on infinite lists, because of course there is no last element to remove. - Cale

Am Sonntag, 10. April 2005 08:44 schrieb Kaoru Hosokawa:
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
This is as far as I got:
init xs = foldr left [] xs
left :: a -> [a] -> [a] left x [] = [] left x1 : (x2 : xs) = x1 : (left x2 xs)
Try left :: (Bool, [a]) -> (Bool, [a]), res :: (Bool, [a]) -> [a], init' = res . foldr left (False, []) for example. It's not too difficult then.
But this returns [] and doesn't work. I can't get "left" to know that it is working with the rightmost element. It just throws away every element when its right hand side is empty.
I found a solution that works for Strings, but I am looking for a more general solution. This exercise may yet again be one of those that is difficult to solve with my current knowledge of Haskell, but I'm asking anyway.
I cannot imagine how you could do it for Strings, but not for general lists. Mind sending me the code? Hope this helps, Daniel

Daniel Fischer
On second thoughts, I think Maybe [a] is nicer than (Bool, [a]).
Cool, this was my idea, too. Best regards, Christop Bauer -- let () = let rec f a w i j = Printf.printf "%.20f\r" a; let a1 = a *. i /. j in if w then f a1 false (i +. 2.0) j else f a1 true i (j +. 2.0) in f 2.0 false 2.0 1.0

Kaoru Hosokawa
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
This is as far as I got:
init xs = foldr left [] xs
left :: a -> [a] -> [a] left x [] = [] left x1 : (x2 : xs) = x1 : (left x2 xs)
But this returns [] and doesn't work. I can't get "left" to know that it is working with the rightmost element. It just throws away every element when its right hand side is empty.
I found a solution that works for Strings, but I am looking for a more general solution. This exercise may yet again be one of those that is difficult to solve with my current knowledge of Haskell, but I'm asking anyway.
Ok, my second haskell program ;-): module Init where import Maybe left :: a -> Maybe [a] -> Maybe [a] left x None = (Just []) left x (Just l) = (Just (x:l)) init :: [a] -> [a] init xs = fromJust . foldr left Nothing xs Sure, there is a better solution... Best Regards, Christoph Bauer -- let () = let rec f a w i j = Printf.printf "%.20f\r" a; let a1 = a *. i /. j in if w then f a1 false (i +. 2.0) j else f a1 true i (j +. 2.0) in f 2.0 false 2.0 1.0

On Mon, 11 Apr 2005, Christoph Bauer wrote:
Kaoru Hosokawa
writes: I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
This is as far as I got:
init xs = foldr left [] xs
left :: a -> [a] -> [a] left x [] = [] left x1 : (x2 : xs) = x1 : (left x2 xs)
But this returns [] and doesn't work. I can't get "left" to know that it is working with the rightmost element. It just throws away every element when its right hand side is empty.
I found a solution that works for Strings, but I am looking for a more general solution. This exercise may yet again be one of those that is difficult to solve with my current knowledge of Haskell, but I'm asking anyway.
Ok, my second haskell program ;-):
module Init where
import Maybe
left :: a -> Maybe [a] -> Maybe [a] left x None = (Just []) left x (Just l) = (Just (x:l))
left x = Just . maybe [] (x:)
init :: [a] -> [a] init xs = fromJust . foldr left Nothing xs
fromMaybe (error "init: empty list") instead of fromJust
Sure, there is a better solution...
Extended question: How to do it without foldr? :-) init xs = zipWith const xs (tail xs) But this does not check for empty lists. :-(

Am Montag, 11. April 2005 15:59 schrieb Christoph Bauer:
Ok, my second haskell program ;-):
module Init where
import Maybe
left :: a -> Maybe [a] -> Maybe [a] left x None = (Just [])
^^^^^^^^ Nothing, as below :-)
left x (Just l) = (Just (x:l))
init :: [a] -> [a] init xs = fromJust . foldr left Nothing xs
Sure, there is a better solution...
I don't think so. As far as I see, it's impossible to do it with just init xs = foldr fun val xs, (unless we use some dirty trick) because we must have fun x (init ys) = x:init ys for any nonempty list ys and init [] = val forces val to be 'error "init of empty List"' or something of the sort and this has to be evaluated when we reach the end of the list, for we would need fun _ (error "blah") = [] for nonempty lists. Dirty trick: unsafePerformIO import System.IO.Unsafe fun :: a -> [a] -> [a] fun x xs = unsafePerformIO ((xs `seq` (return (x:xs))) `catch` (\ _ -> return [])) init3 :: [a] -> [a] init3 = foldr fun (unsafePerformIO (ioError (userError "init of []"))) *Init> init3 [] *** Exception: user error (init of []) *Init> init3 [1] [] *Init> init3 [1 .. 10] [1,2,3,4,5,6,7,8,9] Though this works, it is utterly horrible and despicable. DON'T DO THAT!!!!!
Best Regards, Christoph Bauer
Cheers, Daniel

Here's a solution:
init :: [a] -> [a] init xs = tail (foldr keep [] xs) where keep :: a -> [a] -> [a] keep x [] = [x] keep x [y] = [x,x] keep x (y:z:zs) = x:x:y:zs
--Ham At 3:44 PM +0900 2005/4/10, Kaoru Hosokawa wrote:
I've been working through Thompson's exercises and got to one I could not solve. It's Exercise 9.13. This is where I need to define init using foldr.
init :: [a] -> [a] init "Greggery Peccary" ~> "Greggary Peccar"
This is as far as I got:
init xs = foldr left [] xs
left :: a -> [a] -> [a] left x [] = [] left x1 : (x2 : xs) = x1 : (left x2 xs)
But this returns [] and doesn't work. I can't get "left" to know that it is working with the rightmost element. It just throws away every element when its right hand side is empty.
I found a solution that works for Strings, but I am looking for a more general solution. This exercise may yet again be one of those that is difficult to solve with my current knowledge of Haskell, but I'm asking anyway.
-- Kaoru Hosokawa khosokawa@gmail.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- ------------------------------------------------------------------ Hamilton Richards, PhD Department of Computer Sciences Senior Lecturer The University of Texas at Austin 512-471-9525 1 University Station C0500 Taylor Hall 5.138 Austin, Texas 78712-0233 ham@cs.utexas.edu hrichrds@swbell.net http://www.cs.utexas.edu/users/ham/richards ------------------------------------------------------------------

On Tue, 12 Apr 2005, Hamilton Richards wrote:
Here's a solution:
init :: [a] -> [a] init xs = tail (foldr keep [] xs) where keep :: a -> [a] -> [a] keep x [] = [x] keep x [y] = [x,x] keep x (y:z:zs) = x:x:y:zs
Nice idea! One case can be eliminated.
init :: [a] -> [a] init xs = tail (foldr keep [] xs) where keep :: a -> [a] -> [a] keep x [] = [x] keep x (_:zs) = x:x:zs

At 6:53 PM +0200 2005/4/12, Henning Thielemann wrote:
On Tue, 12 Apr 2005, Hamilton Richards wrote:
Here's a solution:
init :: [a] -> [a] init xs = tail (foldr keep [] xs) where keep :: a -> [a] -> [a] keep x [] = [x] keep x [y] = [x,x] keep x (y:z:zs) = x:x:y:zs
Nice idea!
One case can be eliminated.
init :: [a] -> [a] init xs = tail (foldr keep [] xs) where keep :: a -> [a] -> [a] keep x [] = [x] keep x (_:zs) = x:x:zs
Yes, much nicer! Thanks, --Ham -- ------------------------------------------------------------------ Hamilton Richards, PhD Department of Computer Sciences Senior Lecturer The University of Texas at Austin 512-471-9525 1 University Station C0500 Taylor Hall 5.138 Austin, Texas 78712-0233 ham@cs.utexas.edu hrichrds@swbell.net http://www.cs.utexas.edu/users/ham/richards ------------------------------------------------------------------

I just realized that I was not replying to the list. Sorry about that and thank you all for contributing to the thread. -- Kaoru Hosokawa khosokawa@gmail.com
participants (7)
-
Bernard Pope
-
Cale Gibbard
-
Christoph Bauer
-
Daniel Fischer
-
Hamilton Richards
-
Henning Thielemann
-
Kaoru Hosokawa