2012-07-06 40 views
1

我是Haskell的新手,正在努力研究如何在列表結束時停止我的程序爆炸。從Haskell函數中刪除'take'

作爲一個例子,我有一個鏡像XY軸的字符列表的功能。

如何在沒有take的情況下重寫?

mirrorXY' :: [[a]] -> [[a]] 
mirrorXY' m = (map head m) : mirrorXY' (map tail m) 
mirrorXY m = take (length $ m!!0) $ mirrorXY' m 

P.S.我剛剛發現transpose,但我仍然想要一個答案。

+0

另請參閱[轉置](http://www.haskell.org/ghc/docs/latest/html/libraries/base/src/Data-List.html#transpose) – Rotsor 2012-07-06 17:29:51

+0

@Rotsor,我已經提到過在你發表評論之前,在問題中使用'transpose'。 – fadedbee 2012-07-08 16:11:38

回答

2

您需要處理空的列表,例如

mirrorXY [] = [] 
mirrorXY ([]:_) = [] 
mirrorXY m = (map head m) : mirrorXY (map tail m) 

這假定列表的長度是一致的。

更有力,像

safeHead [] = Nothing 
safeHead (a:_) = Just a 

mirrorXY [] = [] 
mirrorXY m = case mapM safeHead m of 
       Nothing -> [] 
       Just a -> a : mirrorXY (map tail m) 

停靠太短第一個列表上。請注意,這使用Maybe的monad實例通過mapM safeHead m線路進行短路。


人們甚至可以寫上一版本更簡潔,使用maybe

mirrorXY [] = [] 
mirrorXY m = maybe [] (: mirrorXY (map tail m)) $ mapM safeHead m 

但是,這並不一定清楚。

4

首先,你mirrorXY'可以用高階函數mapiterate,而不是直接遞歸編寫:

mirr m = map (map head) . iterate (map tail) $ m 

...這打擊了在碰到空列表,因爲你已經發現:

*Main> map (map head) . iterate (map tail) $ [[1..4],[2..5],[3..6]] 
[[1,2,3],[2,3,4],[3,4,5],[4,5,6],[*** Exception: Prelude.head: empty list 

讓我們嘗試一下沒有第一部分:

*Main> iterate (map tail) $ [[1..4],[2..5],[3..6]] 
[[[1,2,3,4],[2,3,4,5],[3,4,5,6]],[[2,3,4],[3,4,5],[4,5,6]],[[3,4],[4,5],[5,6]],[ 
[4],[5],[6]],[[],[],[]],[*** Exception: Prelude.tail: empty list 
*Main> 

所以很容易修復:我們只需要停止在碰到[]輸入列表:

*Main> takeWhile (not.null.head) . iterate (map tail) $ [[1..4],[2..5],[3..6]] 
[[[1,2,3,4],[2,3,4,5],[3,4,5,6]],[[2,3,4],[3,4,5],[4,5,6]],[[3,4],[4,5],[5,6]],[ 
[4],[5],[6]]] 

因此,功能

mirr xs = map (map head) . takeWhile (not.null.head) . iterate (map tail) $ xs 

這預示着所有的子表都同樣長度(或至少所述第一個是最短的),但是,很容易通過調整測試中takeWhile修復:

mirr xs = map (map head) . takeWhile (all (not.null)) . iterate (map tail) $ xs 
+0

謝謝你的回答,但另一個是可以理解的。我認爲對於Haskell新手來說,這種無點式的風格有點難。 – fadedbee 2012-07-06 12:35:45

+0

@chrisdew YMMV。 :) – 2012-07-06 12:37:56

+0

是的,我希望能夠在幾個月內閱讀無點代碼。 – fadedbee 2012-07-06 13:20:53