乍一看,我打算建议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
,虽然它只适用于一种非常特殊的功能......