因此,正如標題所說,我應該創建一個函式,該函式接受一個串列并回傳沒有重復項的串列,但我不能使用串列理解,只能使用高階函式和 lambda。
我從另一個用戶問題中找到了這段代碼。
has :: (Eq a) => [a] -> a -> Bool
has [] _ = False
has (x:xs) a
| x == a = True
| otherwise = has xs a
unique :: (Eq a) => [a] -> [a]
unique [] = []
unique (x:xs)
| has xs x = unique xs
| otherwise = x : unique xs
我明白它是如何作業的,但我不明白我怎么能用高階函式做同樣的事情。我是 Haskell 的新手,所以任何提示都將不勝感激。
uj5u.com熱心網友回復:
但我不能使用串列理解,只能使用高階函式和 lambda。
好訊息是:您不使用串列理解。
你可以在foldr :: (a -> b -> b) -> b -> [a] -> b這里作業。這里第一個函式采用型別元素a和串列其余部分的函式的“結果”(因此這里是剩余元素的唯一元素串列)。因此,您的函式應該檢查該元素是否已經出現在該結果中。因此,您可以通過以下方式實作:
unique :: Eq a => [a] -> [a]
unique = foldr f []
where f x xs
| … = …
| otherwise = …
您仍然需要填寫的…部分。您甚至可以將其概括為 any Foldable:
unique :: (Eq a, Foldable f) => f a -> [a]
unique = foldr f []
where f x xs
| … = …
| otherwise = …
uj5u.com熱心網友回復:
您已foldr在另一個答案中被建議。這適用于您的has功能,但不適用于unique. 可以系統化對 foldr 的重構,正如 Graham Hutton 的論文“A tutorial on the universality and expressiveness of fold”中所教導的那樣。
本質上當g = fold f v且僅當可以寫成這樣的形式,
g [ ] = v
g (x : xs) = f x (g xs)
讓我們看看這對函式是如何作業的has。 注意:我將翻轉引數的順序has以使其更簡單。
has :: (Eq a) => a -> [a] -> Bool
has _ [] = False
has a (x:xs)
| x == a = True
| otherwise = has a xs
我們需要弄清楚我們的g,v和f。
g- 這個函式has不完全是我們的函式g,因為后者只接受一個串列作為引數,has也接受一個a. 而是g = has a。
v- 那是微不足道的,v = False
f- 根據以上應該滿足f x (g xs) = g (x : xs), 即
f x (has a xs)
| x == a = True
| otherwise = has a xs
在這里,我們將引數推廣has a xs到 any y,導致
f x ys =
| x == a = True
| otherwise = ys
或者如果您愿意,可以使用它的 lambda 形式,
f = \x ys ->
| x == a = True
| otherwise = ys
到達,
has a = foldr f False
where
f x ys =
| x == a = True
| otherwise = ys
現在讓我們看看為什么它不適用于unique.
unique :: (Eq a) => [a] -> [a]
unique [] = []
unique (x:xs)
| has x xs = unique xs
| otherwise = x : unique xs
同樣,我們需要弄清楚我們的g,v和f。這g當然是我們的unique職能。,v = []基本情況。最后從第二個方程中g得出f應該滿足f x (g xs) = g (x : xs).
f x (unique xs) =
| has x xs = unique xs
| otherwise = x : unique xs
再次讓 abstract overunique xs得到一個定義f,
f x ys =
| has x xs = ys
| otherwise = x : ys
這沒有成功,因為xs那仍然在定義中。請注意,該屬性g (x : xs) = f x (g xs)指定遞回是通過在僅作用于x的結果的每個步驟上應用 lambda 來執行的g xs。它不作用于 xs。
我們可以改變的定義unique使它成為一個檔案夾。您的定義檢查是否x在xs,即在未處理的元素串列中,如果是,則不添加它。我們可以做相反的事情,x在處理過的元素串列中檢查是否已經添加了。
unique2 :: (Eq a) => [a] -> [a]
unique2 [] = []
unique2 (x:xs)
| has x zs = zs
| otherwise = x : zs
where zs = unique2 xs
有了這個改變,我們f應該滿足,
f x (unique2 xs) =
| has x zs = zs
| otherwise = x : zs
where zs = unique2 xs
并抽象出來unique2 xs,我們得到,
f x ys =
| has x ys = ys
| otherwise = x : ys
因此,
unique2 = foldr f []
where
f x ys =
| has x ys = ys
| otherwise = x : ys
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/536665.html
標籤:哈斯克尔函数式编程
上一篇:Haskell求和資料型別中“多重宣告”的解決方案?
下一篇:哈斯克爾紙牌游戲
