Применить функцию к списку и передать ее результат в конструктор? - PullRequest
1 голос
/ 04 февраля 2011

Как можно просто написать 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.

Ответы [ 4 ]

2 голосов
/ 04 февраля 2011

Нет особо простого или компактного метода, но вы можете попробовать это:

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]
1 голос
/ 04 февраля 2011

В принципе не существует простого способа сделать это без перечисления всех четырех аргументов, потому что в противном случае, как вы можете убедиться, что список имеет правильное число (4) элементов?

1 голос
/ 04 февраля 2011

На первый взгляд, я собирался предложить 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))

Теперь вы можете легко заставить 'sort' работать со своей структурой 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 к списку, отображает функцию списка поднял на все элементы списка, а затем тянет список обратно в Структура QT. Лучшее имя для listOpOnQT может быть liftQT, хотя оно работает только для особого вида функций ...

0 голосов
/ 04 февраля 2011

, применяя его к каждому элементу списка [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]
...