1

如何只写flipv一次将其应用于 list 的每个元素[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。

4

4 回答 4

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]
于 2011-02-04T16:24:04.620 回答
1

如果不枚举所有四个参数,基本上没有简单的方法可以做到这一点,否则,您如何确保列表具有正确数量 (4) 的元素?

于 2011-02-04T19:52:56.100 回答
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,虽然它只适用于一种非常特殊的功能......

于 2011-02-04T18:40:02.203 回答
-1

将其应用于列表 [se, sq, nw, ne] 的每个元素,将结果(当然不是列表)提供给 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]
于 2011-02-04T17:59:50.563 回答