繁体   English   中英

Haskell:使用(curry snd)计算列表的长度

[英]Haskell: Calculate the length of a list using (curry snd)

我得到了一个使用foldr Haskell 函数计算列表长度的作业,所以我做了这两个例子

flength :: [a] -> Int
flength = foldr (\ _ n -> n+1) 0

flength' :: [a] -> Int
flength' l = foldr aux 0 l
    where
        aux _ n = n+1

然后,作为个人挑战,教授要求我们使用snd函数,昨天我想出了这个:

flength'' :: [a] -> Int
flength'' = foldr ((+1).(curry snd)) 0

我想要发生的是这个函数将把列表的头部h和累加器0变成对(h,0)然后返回0然后将它应用到函数(+1)

我希望这是递归完成的,最后有效地给了我列表的长度。

相反,我收到此错误消息:

    [1 of 1] Compiling Main             ( f1.hs, interpreted )

f1.hs:54:24: error:
    * No instance for (Num (Int -> Int))
        arising from an operator section
        (maybe you haven't applied a function to enough arguments?)
    * In the first argument of `(.)', namely `(+ 1)'
      In the first argument of `foldr', namely `((+ 1) . (curry snd))'
      In the expression: foldr ((+ 1) . (curry snd)) 0 xs
Failed, modules loaded: none.

为什么会发生这种情况以及如何使此代码正常工作?

让我们把所有的工具都摆在我们面前,就像一个好的工匠一样:

foldr :: (a -> b -> b) -> b -> [a] -> b
snd   :: (a, b) -> b

首先,我们注意到sndfoldr不太适合。 因此,让我们像您一样使用curry ,并将curry snd添加到我们的小型工具库中:

foldr     :: (a -> b -> b) -> b -> [a] -> b
curry snd ::  a -> b -> b

这看起来很有希望。 现在我们需要将curry snd的结果加1 ,否则我们只是在写flip const 让我们从一个 lambda 开始:

\a b -> 1 + curry snd a b
= \a b -> ((+1) . curry snd a) b

我们现在可以推b并最终得到

\a -> (+1) . curry snd a
= \a -> (.) (+1) (curry snd a)
= \a -> ((.) (+1)) (curry snd a)
= \a -> (((.) (+1)) . curry snd) a

现在我们也可以从两边对a进行 eta-reduce 并最终得到

(((.) (+1)) . curry snd) = ((+1) . ) . curry snd

因此,您的第三个变体将是

flength'' = foldr (((+1) . ) . curry snd) 0

现在,您为什么会收到错误消息? 你很接近(+1) . curry snd (+1) . curry snd ,但类型不工作:

(+1)      :: Int -> Int
--            v                    v
(.)       :: (b ->  c)    -> (a -> b       ) -> a -> c
curry snd ::                  t -> (x -> x)
              ^                     ^

但是在您的情况下, (.)签名中的b不匹配。 其中一个是Int ,另一个是函数。

TL;DR : 如果你想写f (gxy) point-free,写((f.) . g)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM