2011-02-04 161 views
1

如何才能將flipv一次性應用到列表[se, sq, nw, ne]的每個元素,給Q構造函數提供結果(不是當然列表)?將函數應用於列表並將其結果傳遞給構造函數?

data (Eq a, Show a) => QT a = C a | Q (QT a) (QT a) (QT a) (QT a) 
    deriving (Eq, Show) 

flipv :: (Eq a, Show a) => QT a -> QT a 
flipv (C a) = C a 
flipv (Q nw ne se sw) = Q (flipv se) (flipv sw) (flipv nw) (flipv ne) 

編輯:注意這個其實是錯誤的,因爲指針應爲:NW NE SW SE。

+1

+1,因爲我很樂意試着回答=) – 2011-02-04 18:42:50

+3

順便說一句,你應該從`data`類型中刪除`(Eq a,Show a)=>`。有關解釋,請參閱http://learnyouahaskell.com/making-our-own-types-and-typeclasses#algebraic-data-types(但在Haskell中,在數據聲明中永遠不會添加類型類約束是非常強大的約定。 ..「) – Landei 2011-02-04 21:17:00

回答

2

沒有特別簡單和緊湊的方法,但你可以試試這個:

flipv :: (Eq a, Show a) => QT a -> QT a 
flipv (C a) = C a 
flipv (Q nw ne se sw) = Q se' sw' nw' ne' 
    where [nw', ne', se', sw'] = map flipv [nw, ne, se, sw] 
+0

似乎很難讀,我正在尋找一個優雅的方式... – gremo 2011-02-04 17:07:28

+0

@Gremo,對我來說看起來相當不錯。也許你的眼睛需要訓練。或者它可能看起來很醜,因爲你期望更簡單一些 - 但是你想要的卻不能在類型系統中表達出來。 – luqui 2011-02-05 04:28:33

-1

它應用到列表中的每個元素[SE,平,西北,東北],給出的結果(未作爲課程列表)給Q構造函數?

取一個列表並拋出一個QT。

data (Eq a, Show a) => QT a = C a | Q (QT a) (QT a) (QT a) (QT a) 
    deriving (Eq, Show) 

flipv :: (Eq a, Show a) => [a] -> QT a 
flipv [nw, ne, se, sw] = Q (C se) (C sw) (C nw) (C ne) 

main = do 
    print (Q (C 1) (C 2) (C 3) (C 4)) 
    (print . flipv) [1, 2, 3, 4] 
1

乍一看,我會建議toListfromList。這是更多的代碼,但它最終使優雅的組合。

toList :: QT a -> [QT a] 
toList (Q w x y z) = [w,x,y,z] 

fromList :: [QT a] -> QT a 
fromList [w,x,y,z] = Q w x y z 

listOpOnQT :: ([QT a] -> [QT a]) -> QT a -> QT a 
listOpOnQT _ (C a) = C a 
listOpOnQT f q  = fromList . map (listOpOnQT f) . f . toList $ q 

flipv :: QT a -> QT a 
flipv = listOpOnQT reverse 

在ghci中

ghci> let q = Q (Q (C 1) (C 2) (C 3) (C 4)) (C 22) (C 33) (C 44) 
ghci> q 
Q (Q (C 1) (C 2) (C 3) (C 4)) (C 22) (C 33) (C 44) 
ghci> flipv q 
Q (C 44) (C 33) (C 22) (Q (C 4) (C 3) (C 2) (C 1)) 

您可以輕鬆地讓你的QT結構 '排序' 工作爲好,現在鬆散測試。

import Data.List (sort) 
instance (Ord a) => Ord (QT a) where 
    compare (C x) (C y) = x `compare` y 
    compare (C x) _ = LT 
    compare _ (C x) = GT 
    compare _ _ = EQ 

sortv :: (Ord a) => QT a -> QT a 
sortv = listOpOnQT sort 

測試與前ghci的會話的一部分......

ghci> sortv it 
Q (C 22) (C 33) (C 44) (Q (C 1) (C 2) (C 3) (C 4)) 
ghci> sortv q 
Q (C 22) (C 33) (C 44) (Q (C 1) (C 2) (C 3) (C 4)) 

通知排序翻轉Q和只是簡單q都具有相同的結果就出來了(因此可能排序工作!耶) 。你可能想要選擇更好的實現compare,我只是把它扔到一起看到的東西發生。


那麼它是如何工作的?

魔法醬,你可能已經猜到了,是listOpOnQT。在非平凡的情況下,它將QT結構變成列表,將listy函數應用於列表,將listy函數映射到列表的所有元素上,然後將列表拉回到QT結構中。爲listOpOnQT一個更好的名字可能是liftQT,但它僅適用於一個非常特殊的功能...

1

有基本上沒有簡單的方法來做到這一點不枚舉所有四個參數,因爲否則的話,你怎麼能確保該列表有正確的編號(4)?