![](/img/trans.png)
[英]How can I write the following haskell code with higher order functions?
[英]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.