2012-12-14 39 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