Memo
Memo

Reputation: 89

Pass output from a function as input in another function in Haskell

How can one pass output from a function as an input in another function.

For example I have those two functions

collatz :: (Integral a) => a -> [a]
collatz 1 = [1]  
collatz n  
    |even n = n:collatz (n `div` 2)  
    |odd n = n:collatz (n*3 + 1) 

And my another function

length' [] = 0
length' (x:xs) = 1 + length' xs

I want to calculate the length of a list, which was output from my collatz function.

finally I want calculate completely this

numLongChains :: Int  
numLongChains = length (filter isLong (map collatz [1..100]))  
    where isLong xs = length xs > 15  

But step by step.

Upvotes: 2

Views: 2243

Answers (2)

GreenhouseVeg
GreenhouseVeg

Reputation: 647

You are talking about function composition:

-- assuming signature length' :: [a] -> Int   
composed :: (Integral a) => a -> Int
composed = length' . collatz

I am not sure what you mean by 'step by step', but for your second question, it would be:

numLongChains :: (Integral a) => [a] -> Int
numLongChains = length' . (filter isLong) . (map collatz)
    where isLong xs = length' xs > 15 

I made it a unary function so it can work with any list, not just [1..100].

Upvotes: 5

Rein Henrichs
Rein Henrichs

Reputation: 15605

The length' of the collatz sequence for n is \n -> length' (collatz n). This pattern is so common that we gave it a name: f . g = \x -> f (g x). We call this "function composition". Replacing f, g, and x above with length', collatz, and n, we get length' . collatz = \n -> length' (collatz n). So:

collatzLength = length' . collatz

As an aside, instead of writing isLong as you do, we can use function composition here too, albeit in a slightly less obvious way:

isLong xs = length' xs > 15
isLong = \xs -> length' xs > 15
isLong = \xs -> (>) (length' xs) 15
isLong = \xs -> (> 15) (length' xs) -- this is the less obvious bit
isLong = (> 15) . length'

So the question "is the collatz sequence for the number n longer than 15?" can now be written as:

isLongSequence = isLong . collatz

So the long sequences for the numbers [1..100] are

filter isLongSequence [1..100]

or with

longSequences = filter isLongSequence

it's

longSequences [1..100]

now, we can write numLongChains as

numLongChains = length' . longSequences

The number of long chains is the number (length) of (the list of) long sequences.

Now, to show that this is equivalent to your definition, you need to know a rule (theorem) about map and filter:

filter p . map f = filter (p . f)

So

\xs -> filter isLong (map collatz xs)

is the same as

filter isLong . map collatz

is the same as

filter (isLong . collatz)

is the same as

filter isLongSequence

is the same as

longSequences

Upvotes: 2

Related Questions