簡體   English   中英

Haskell:如何返回列表的可能拆分列表

[英]Haskell: How to return a list of possible splits of a list

我正在嘗試編寫一個名為split的函數,它接受一個列表並返回所有不同可能性的對列表以對其進行分區,例如

split [4,3,6] = [([],[4,3,6]),([4],[3,6]),([4,3],[6]),([4,3,6],[])]

現在我寫了這個

split :: [a] -> [([a],[a])]
split []     = [([],[])]
split (x:xs) = ([],(x:xs)):(zip (map (x:) (map fst split(xs))) (map snd split(xs)))

一段代碼和Hugs以及我選擇的翻譯讓我知道了

ERROR file:.\split.hs:3 - Type error in application
*** Expression     : map snd split xs
*** Term           : map
*** Type           : (e -> f) -> [e] -> [f]
*** Does not match : a -> b -> c -> d

錯誤信息。 我到底做錯了什么? 為什么(map snd split xs)屬於類型
(a-> b - > c - > d)?

你錯了你的parens。 嘗試

split (x:xs) = ([],(x:xs)):(zip (map (x:) (map fst (split xs))) (map snd (split xs)))

Haskell不像C和Java那樣使用括號進行函數調用。 當您編寫map fst split(xs)這與map fst split xs相同,即編譯器認為您嘗試使用三個參數調用map 因此,您需要將調用split如下所示: map fst (split xs)

你有效地嘗試編寫的是一個列表的簡單拉鏈 實現它的最簡單方法是

import Data.List (inits, tails)

split xs = zip (inits xs) (tails xs)

這是另一種定義:

splits :: [a] -> [(a, a)]
splits xs = map (flip splitAt xs) [0 .. length xs]

不可否認,這不是很有效,但至少它簡潔:-)

另一個版本,甚至更短,而且可能更有效,使用initstailsData.List

splits :: [a] -> [(a, a)]
splits xs = zip (inits xs) (tails xs)

現在讓我們玩得開心吧。 我們可以將initstails寫為foldr ,其中我們使用initsAtailsA來表示所謂的折疊代數

inits :: [a] -> [[a]]
inits = foldr initsA [[]]

initsA :: a -> [[a]] -> [[a]]
initsA x xss = [] : map (x:) xss

tails :: [a] -> [[a]]
tails = foldr tailsA [[]]

tailsA :: a -> [[a]] -> [[a]]
tailsA x xss = (x : head xss) : xss

使用這些代數,我們可以進一步組合它們:

splits :: [a] -> [([a], [a])]
splits = foldr splitsA [([], [])]

splitsA :: a -> [([a], [a])] -> [([a], [a])]
splitsA xy xyss = zip (initsA xy xss) (tailsA xy yss)
  where (xss, yss) = unzip xyss

所以現在我們splits定義為單個foldr

暫無
暫無

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

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