2012-12-14 34 views
3

我需要幫助理解下面的Haskell功能,哈斯克爾 - 需要幫助理解這種分裂功能

split l = rr++[ll] 
      where 
       split = foldl 
         (\ (c,a) e -> 
           case c of 
           [] -> ([e],a) 
           _ -> if e*(head c) < 0 
            then ([e],a++[c]) 
            else (c++[e],a)) 
         ([],[]) 
       (ll,rr) = split l 

> split [1,2,3,-1,-2,7,4,-3,-5,-6,2,3] 
[[1,2,3],[-1,-2],[7,4],[-3,-5,-6],[2,3]] 

如上看到它分裂連續編號在單獨的列表相同的符號。在Scheme中,跟蹤器功能對逐步評估表達式非常有幫助,但不幸的是,GHCi沒有這樣的功能。請幫助我逐步完成代碼。謝謝!

注意:我理解函數的foldl部分。這是模式匹配部分(split l = rr++[ll](ll,rr) = split l)真的讓我困惑!

+0

哪種模式匹配部分 - 您是指案例表達式?那怎麼會讓你困惑? –

+0

我的意思是,算法本身非常混亂,而且,徹頭徹尾的錯誤:) - 在一個以0開頭的列表上試試它。但是你應該清楚它是否是那種語法或者你被困在什麼地方。 –

+0

GHCi _can_值得追查。我不記得目前如何,雖然... – javawizard

回答

8

我想在這裏可以混淆大家的是,其實wheresplit其實從split在頂層完全不同 - 內一個「陰影」外一個,就像本地變量覆蓋全球那些。下面的代碼做同樣的事情:

split l = rr++[ll] 
      where 
       notSplit = foldl 
         (\ (c,a) e -> 
           case c of 
           [] -> ([e],a) 
           _ -> if e*(head c) < 0 
            then ([e],a++[c]) 
            else (c++[e],a)) 
         ([],[]) 
       (ll,rr) = notSplit l 

所以我們稱之爲notSplit輸入列表,它會返回一個元組(ll,rr),然後我們計算rr ++ [ll]並返回。 (正如我上面所說的,該算法在包括零的列表上是不必要的模糊,低效和不正確的,但這完全是另一個問題)。

+0

謝謝,我確實認爲內部拆分與外部拆分相同。謝謝! :) – Faizal

4

請仔細考慮foldl表達式產生的結果。當它通過列表時,它累積了一個元組(c, a)。這個元組的第一個元素c始終是一個數字列表。 a是數字列表---這恰好就是你想要返回的列表。

當您收到一個新號碼時,如果它的號碼與c中的號碼相同,則將其添加到c。如果它有一個不同於c中的當前標記,那麼您將所有c並將其存入a

最後,您會得到最後一個值爲ca的元組。 a幾乎就是您想要的結果,除非它不完整:您需要將c添加到它。所以表達式

(ll, rr) = split l 

的最末端取的split的結果(這是ca)並分配到cllarr。最後的答案是rr,最後是ll

+0

你的解釋真的很清楚!謝謝! :)我會盡快答覆你的答案。 – Faizal