繁体   English   中英

我如何在 haskell 中修复这个更高阶的 function 代码?

[英]How can i fix this higher order function code in haskell?

我想修复这段代码

h :: (a -> b) -> [a] -> [b]
h f = foldr (\x y -> f x : y) []

如果我将h (+100) [1,2,3,4,5]放入 GHCI

它返回给我[101,202,303,404,505]

当我把 h (*10) [1,2,3,4,5]然后

我想获得[10,200,3000,40000,500000]列表

谁能帮我修复这段代码?

您在这里实现了一个map ,但是为了多次重复相同的操作,您需要对尾部y执行映射:

h :: (a -> a) -> [a] -> [a]
h f = foldr (\x y -> f x : map f y) []

正如Willem Van Onsem 的回答那样,解决一般问题需要O(n^2)时间来计算前n元素,因为 function 必须应用k次才能计算第k个元素。

为了有效地解决这类问题,您需要利用一些额外的结构。 根据您的示例,我认为最明显的方法是考虑semigroup actions 也就是说,与其重复应用任意 function ,不如寻找一种有效的方法来表示 function 的组合。 例如, (*x)可以用x表示,允许(*x). (*y) (*x). (*y)x*y表示。

为了应用这个想法,我们首先需要转换 Willem 的解决方案以使组合明确。

h :: (a -> a) -> [a] -> [a]
h f0 as0 = go as0 f0
  where
    go [] _ = []
    go (a:as) f = f a : go as (f0 . f)

如果我们愿意,我们可以把它写成折叠:

h :: (a -> a) -> [a] -> [a]
h f0 as = foldr go stop as f0
  where
    stop _ = []
    go a r f = f a : r (f0 . f)

现在我们已经使用累加器(这是一个函数)构建了 function。 当我们在累加器上作曲时,应用它的速度会越来越慢。 我们想用一个我们可以快速“应用”的累加器来替换那个累加器。

{-# language BangPatterns #-}
import Data.Semigroup

repeatedly :: Semigroup s => (s -> a -> a) -> s -> [a] -> [a]
repeatedly act s0 as = foldr go stop as s0
  where
    stop _ = []
    go a r !s = act s a : r (s0 <> s)

现在您可以使用,例如,

repeatedly (\(Product s) -> (s*)) (Product 10) [1..5]
==> [10,200,3000,40000,500000]

repeatedly (\(Sum s) -> (s+)) (Sum 100) [1..5]
==> [101,202,303,404,505]

在其中的每一个中,您都会累积一个乘以当前列表元素的乘积/总和。

暂无
暂无

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

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