一見、提案してみようと思いましtoListたfromList。それはより多くのコードですが、最終的にはエレガントな構成を可能にします。
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