[英]Haskell function for list length
To calculate length of a list, using a foldr, one would do something like: 要使用foldr计算列表的长度,可以执行以下操作:
foldr (\_ acc -> acc + 1) 0
Expanding further on the idea that the folding function needs to increment the second argument, i came up with this (and it's wrong): 进一步扩展折叠函数需要增加第二个参数的想法,我想出了这个(这是错误的):
foldr ((+1) . (flip const)) 0`
Further inspection of the type reveals this: 进一步检查该类型揭示了这一点:
(+1) . (flip const) :: Num (c -> c) => a -> c -> c
Haskell higher order function to calculate length There's an interesting comment on that page, which i can't understand really Haskell高阶函数计算长度在该页面上有一个有趣的评论,我真的无法理解
foldr (((+1).).(flip const)) 0
Can someone explain how does that composition actually work ? 有人可以解释一下这个组合是如何运作的吗?
First of all, let's focus why foldr ((+1) . (flip const)) 0
is wrong. 首先,让我们关注为什么
foldr ((+1) . (flip const)) 0
是错误的。 You want to increment the second argument only and forget the first one. 您只想增加第二个参数而忘记第一个参数。 Semantically, that's
从语义上讲,就是这样
\_ a -> a + 1
However, you wrote the following: 但是,您写了以下内容:
(+1) . flip const
= (+1) . (\_ a -> a)
= \x -> (+1) . (\_ a -> a) $ x
= \x -> (+1) $ (\_ a -> a) $ x
= \x -> (+1) $ \a -> a
= \_ -> (+1) (\a -> a)
= const ( (+1) (\a -> a))
Which is why you suddenly need Num (c -> c)
, since you're trying to apply (+1)
on id
. 这就是你突然需要
Num (c -> c)
,因为你试图在id
上申请(+1)
。
But you actually meant: 但你实际上意味着:
\_ a -> a + 1
= \_ a -> (+1) a
= \_ -> (+1)
= const (+1)
After all, you want to forget the first argument and use a function f
on the second. 毕竟,你想忘记第一个参数并在第二个参数上使用函数
f
。 All you have to to is to use const f
. 你所
const f
就是使用const f
。
The composition ((+1).).(flip const)
is overly verbose and probably generated by pointfree : 组合
((+1).).(flip const)
过于冗长,可能是由pointfree生成的:
((+1).).(flip const)
= ((\x -> x + 1).) . (\a _ -> a)
= \c -> ((\x -> x + 1).) . (\a _ -> a) $ c
= \c -> ((\x -> x + 1).) $ \_ -> c
= \c -> \f -> (\x -> x + 1) . f $ \_ -> c
= \c -> (\x -> x + 1) . \_ -> c
= \_ c -> (\x -> x + 1) $ c
= \_ c -> c + 1
This is really a comment, but much too long for one. 这真的是一个评论,但对于一个人来说太长了。
Unless you're dealing with weird numbers like lazy Nat
s, you really want 除非你正在处理像懒人
Nat
这样奇怪的数字,否则你真的很想要
length xs = foldl' (\acc _ -> 1 + acc) 0 xs
Making this pointless, 使这毫无意义,
length = foldl' (\acc -> const ((1+) acc)) 0
length = foldl' (const . (1+)) 0
If you like, you can transform the original foldl'
expression into a foldr
form like so: 如果您愿意,可以将原始的
foldl'
表达式转换为foldr
形式,如下所示:
length xs = foldr go id xs 0 where
go _ r acc = r $! 1 + acc
Chewing on go
, 咀嚼
go
,
go _ r acc = ($!) r $ (+) 1 acc
go _ r = ($!) r . (+1)
go _ r = (. (+1)) (($!) r)
go _ = (. (+1)) . ($!)
go = const ((. (+1)) . ($!))
Chewing on length
, 咀嚼
length
,
length = flip (foldr go id) 0
Putting it all together, 把它们放在一起,
length = flip (foldr (const ((. (+1)) . ($!))) id) 0
I, for one, find this point-free form utterly opaque. 就我而言,我发现这种无点形式是完全不透明的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.