将功能的输出作为输入传递给Haskell的另一个功能

时间:2018-12-19 18:28:23

标签: haskell input output

一个函数如何将一个函数的输出作为另一个函数的输入。

例如,我有这两个功能

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

我想计算列表的长度,该列表是从collat​​z函数输出的。

最后我要完全计算

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

但是要一步一步来

2 个答案:

答案 0 :(得分:5)

您正在谈论function composition

-- 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]

答案 1 :(得分:2)

length'的{​​{1}}序列中的collatzn。这种模式非常普遍,我们给它起了一个名字:\n -> length' (collatz n)。我们称其为“功能组合”。用f . g = \x -> f (g x)fg替换上面的xlength'collatz,我们得到n。所以:

length' . collatz = \n -> length' (collatz n)

顺便说一句,除了以一种不太明显的方式,我们也可以在此处使用函数组合,而不是像您那样写collatzLength = length' . collatz

isLong

因此,问题“ n的collat​​z序列长于15吗?”现在可以写成:

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'

所以数字isLongSequence = isLong . collatz 的长序列是

[1..100]

或搭配

filter isLongSequence [1..100]

longSequences = filter isLongSequence

现在,我们可以将longSequences [1..100] 写为

numLongChains

长链的数量是长序列(列表)的数量(长度)。

现在,要证明这与您的定义相同,您需要了解有关map和filter的规则(定理):

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