如何在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,5] 然后

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

谁能帮我修复这个代码

解决方法

您在这里实现了一个 fig1 = figure; plot(n6C(:,1),n6C(:,2),'o-','MarkerIndices',1:10:length(n6C)) hold on plot(n6(:,n6(:,'*-',1:10:length(n6C)) hold on plot(n6B(:,n6B(:,'v-',1:10:length(n6C)) hold off legend('Test 0.5mm','Test 2mm','Test 3mm','location','northeastoutside') grid on title('Wind velocity'); xlabel('Time (s)'); ylabel('Velocity (m/s)'); saveas(fig1,'Vel.jpeg') ,但是为了多次重复相同的操作,您需要对尾部 map 执行映射:

y
,

解决一般问题,如 Willem Van Onsem's answer 所做的那样,需要 O(n^2) 时间来计算前 n 个元素,因为必须应用该函数 k 次来计算第 k 个元素。

有效地解决这类问题,您需要利用一些额外的结构。根据您的示例,我认为最明显的方法是考虑 semigroup actions。也就是说,与其反复应用任意函数,不如寻找一种有效的方式来表示函数的组合。例如,(*x) 可以表示为 x,允许 (*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)

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

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

在每一个中,您累积一个乘积/总和,该乘积/总和与当前列表元素相加/相乘。