簡體   English   中英

使用文件夾Haskell反轉列表

[英]Reverse list of lists using foldr Haskell

我正在嘗試通過使用文件夾反轉Haskell中的列表列表。 有一個我想做的例子:

> reverse'' [[1,2,3],[3,4,5]]
[[5,4,3],[3,2,1]]

和我的代碼(它不起作用):

reverse'':: [[a]]->[[a]]
reverse'' x = foldr (\n acum -> acum:(foldr(\m acum1 -> acum1++[m])) [] n) [[]] x

我的IDE在第二個文件夾的開頭報告了一個錯誤。

為了分析您當前的解決方案,我將您的一線代碼分解為一些輔助函數,並根據其組成推導了它們的類型:

reverse'':: [[a]] -> [[a]]
reverse'' x = foldr f [[]] x
    where
        f :: [a] -> a -> [a]
        f n acum = acum : reverse n

        reverse :: [a] -> [a]
        reverse n = foldr append [] n

        append :: a -> [a] -> [a]
        append m acum = acum ++ [m]

當我嘗試編譯上面的代碼時,ghc抱怨reverse''類型簽名出現以下錯誤:

Expected type: [[a]] -> [[a]] -> [[a]]
  Actual type: [[a]] ->  [a]  -> [[a]]

我做了一些挖掘,然后為了使“ reverse''具有類型[[a]] -> [[a]] ,函數f需要具有類型[a] -> [[a]] -> [[a]] 但是,當前f類型為[a] -> a -> [a] ,或者在這種情況下為[[a]] -> [a] -> [[a]]

以下是正確的類型,但是由於累加器的起始值,所以將一個額外的[]值插入到數組的開頭:

reverse'':: [[a]] -> [[a]]
reverse'' x = foldr f [[]] x
    where
        f :: [a] -> [[a]] -> [[a]]
        f n acum = acum ++ [reverse n]

        reverse :: [a] -> [a]
        reverse n = foldr append [] n

        append :: a -> [a] -> [a]
        append m acum = acum ++ [m]

最終的解決方案

通過將初始累加器值更改為空列表[]而不是空列表[[]]列表,我們得到了一個可行的解決方案:

reverse'':: [[a]] -> [[a]]
reverse'' x = foldr f [] x
    where
        f :: a -> [a] -> [a]
        f n acum = acum ++ [reverse n]

        reverse :: [a] -> [a]
        reverse n = foldr append [] n

        append :: a -> [a] -> [a]
        append m acum = acum ++ [m]

作為單行

如果您真的希望將此作為單線工作,則為:

reverse'' :: [[a]] -> [[a]]
reverse'' = foldr (\n acum -> acum ++ [foldr (\m acum1 -> acum1 ++ [m]) [] n]) []

與工作:

append m acum = acum ++ [m]
append = \m acum1 -> acum1 ++ [m]

reverse n = foldr append [] n
reverse = \n -> foldr append [] n
reverse = foldr append []
reverse = foldr (\m acum1 -> acum1 ++ [m]) []

f n acum = acum ++ [reverse n]
f = \n acum -> acum ++ [reverse n]
f = \n acum -> acum ++ [foldr (\m acum1 -> acum1 ++ [m]) [] n]

reverse'':: [[a]] -> [[a]]
reverse'' x = foldr f [] x
reverse'' x = foldr (\n acum -> acum ++ [foldr (\m acum1 -> acum1 ++ [m]) [] n]) [] x
reverse'' = foldr (\n acum -> acum ++ [foldr (\m acum1 -> acum1 ++ [m]) [] n]) []

附錄:一個明確的遞歸解決方案

這是一個顯式遞歸解決方案(即不使用fold ),提供了mapreverse

reverse :: [a] -> [a]
reverse (x:xs) = reverse xs ++ [x]
reverse []     = []

map :: (a -> b) -> [a] -> [b]
map f (x:xs) = f x : map f xs
map _ [] = []

reverse'' :: [[a]] -> [[a]]
reverse'' ls = reverse $ map reverse ls

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM