簡體   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