Передать вывод из функции как ввод в другую функцию в Haskell - PullRequest
0 голосов
/ 19 декабря 2018

Как можно передать выход из функции как вход в другую функцию.

Например, у меня есть эти две функции

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

И моя другая функция

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

Я хочу вычислить длину списка, который был выведен из моей функции collatz.

наконец, я хочу полностью вычислить это

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

Но шаг за шагом.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

length' последовательности collatz для n равно \n -> length' (collatz n).Этот шаблон настолько распространен, что мы дали ему имя: f . g = \x -> f (g x).Мы называем это «состав функции».Заменив f, g и x выше на length', collatz и n, мы получим length' . collatz = \n -> length' (collatz n).Итак:

collatzLength = length' . collatz

В качестве отступления, вместо того, чтобы писать isLong, как вы, мы также можем использовать здесь композицию функций, хотя и несколько менее очевидным образом:

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'

Таким образом, вопрос "является ли последовательность Коллатца для числа n длиннее 15?"теперь можно записать как:

isLongSequence = isLong . collatz

Таким образом, длинные последовательности для чисел [1..100] равны

filter isLongSequence [1..100]

или с

longSequences = filter isLongSequence

это

longSequences [1..100]

теперь мы можем записать numLongChains как

numLongChains = length' . longSequences

Число длинных цепочек - это количество (длина) (списка) длинных последовательностей.

Теперь, чтобы показать, что это эквивалентно вашему определению, вам нужно знать правило (теорему) о карте и фильтре:

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

То есть

\xs -> filter isLong (map collatz xs)

совпадает с

filter isLong . map collatz

совпадает с

filter (isLong . collatz)

совпадает с

filter isLongSequence

совпадает с

longSequences
0 голосов
/ 19 декабря 2018

Вы говорите о композиции функций :

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

Я не уверен, что вы подразумеваете под «шаг за шагом», но для вашего второго вопроса это будет:

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

Я сделал это унарной функцией, чтобы она могла работать с любым списком, а не только с [1..100].

...