Printing result during recursion in haskell

I begin to learn Haskell and make a program to execute an iterative process:

n -> n/2 (for even n) n -> 3n+1 (for odd n) 

So, I realized:

 chain n | n == 0 = error "What are you on about?" | n == 1 = error "Finished" | rem n 2 == 0 = chain (n `div` 2) | rem n 2 /= 0 = chain (3 * n + 1) 

`Will this work? But these are just calculations behind the scenes, is there a way to make it display or export like a list of results for n at each iteration until it reaches 1, in order to subsequently find the length of the list?

On the side of the note, is there a way to get GHCi to start in a specific folder? (I use windows)

0
source share
5 answers

You could return a list of results in the chain as follows:

 chain n | n == 0 = error "What are you on about?" | n == 1 = [] | rem n 2 == 0 = (n `div` 2) : chain (n `div` 2) | otherwise = (3 * n + 1) : chain (3 * n + 1) 

Now you will get the following results:

 *Main> chain 3 [10,5,16,8,4,2,1] *Main> chain 7 [22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1] 
+2
source

Oh sure. There's even a function from the Data.List module that captures this usage pattern.

 import Data.List (unfoldr) chain 0 = [] chain n = unfoldr fn where f 1 = Nothing fn = let n' | even n = n `div` 2 | otherwise = 3 * n + 1 in Just (n', n') 

Type unoldr: (b β†’ Maybe (a, b)) β†’ b β†’ [a]

b is a state variable that is used to generate the list. The function provided as the first argument to unfoldr should either return Nothing (which means ending the list) or Just (b, a), where a is the item to add to the list and b is the new state variable.

+2
source

is there any way to make it display or export as a list of results for n at each iteration until it reaches 1

You can use Debug.Trace.trace to print log messages to stdout as you evaluate the values. Good for quick debugging.

+2
source

You will notice that the two previous answers use the paradigm of "build the entire list and then output it at the end" rather than "output one item at a time." This is a functional way of doing things.

If you really want to do this in an imperative style, you need to use monadic programming, which is a more complicated topic. Here is an example (do not worry if you cannot understand everything that is happening ... Monads are quite mysterious and magical):

 import Control.Monad.Writer chain :: Int -> (String, [Int]) chain = runWriter . chain' where chain' 0 = return "Failure" chain' 1 = do tell [1] -- write 1 return "Success" -- finished chain' n = do -- write n tell [n] -- calculate next n and recurse if even n then chain' $ n `div` 2 else chain' $ 3 * n + 1 

Which gives such results as:

 *Main> chain 3 ("Success",[3,10,5,16,8,4,2,1]) 

But, as you can see, the writer monad is still just generating the list backstage.

This may seem ineffective. What if you want to print a list of 1,000,000 items? Do you really need to create an entire list? In fact, Haskell's lazy semantics mean that, when possible, Haskell will compile your "assembly of the whole thing forward" and then print its "code in" only to generate and output one element at a time. "

+1
source

The function should simply return a list of items found. This list can be further checked further:

 chain 0 = error "No no no." chain 1 = [1] chain n | rem n 2 == 0 = n : chain (n `div` 2) | otherwise = n : chain (3 * n + 1) 

Here [1] is a list containing only 1 and : is a list constructor that adds an item on the left to the list on the right.

Then the list created by chain can be displayed or used with other functions:

 *Main> chain 5 [5,16,8,4,2,1] *Main> length (chain 31) 107 
+1
source

All Articles