niejednokrotnie pomaga wymyślić niezmienniki i zapisuje dla nich kilka praw zachowania. Tutaj zauważyć, że
reverse xs = reverse xs ++ []
reverse (x:xs) = (reverse xs ++ [x]) ++ []
= reverse xs ++ ([x] ++ [])
= reverse xs ++ (x:[])
reverse (x:(y:xs)) =
= reverse (y:xs) ++ (x:[])
= reverse xs ++ (y:x:[])
......
reverse (x:(y:...:(z:[])...)) =
= reverse [] ++ (z:...:y:x:[])
więc jeśli definiujemy
reverse xs = rev xs [] where
rev (x:xs) acc = rev xs (x:acc)
rev [] acc = acc
mamy ustawiony. :) To znaczy, dla wywołania rev a b
, konkatenacji odwróconej a
i b
jest zachowany pod transformacji biorąc elementu head z a
i poprzedzenie go b
, aża
jest pusty, a potem to tylko b
. To może być nawet wyrażana przy użyciu higher-order function until
poniższym opisie angielskim, jak
{-# LANGUAGE TupleSections #-}
reverse = snd . until (null.fst) (\(a,b)-> (tail a,head a:b)) . (, [])
Możemy również zdefiniować na przykład teraz revappend
funkcja, stosując dokładnie tę samą funkcję wewnętrznej z trochę uszczypnąć, jak my to nazywamy:
revappend xs ys = rev xs ys where
rev (x:xs) acc = rev xs (x:acc)
rev [] acc = acc
robi '[długość XS - 1, xs długość - 2..0]' praca? –
Jeśli nie masz jeszcze ochoty na rekursję, przed spojrzeniem na inne implementacje spróbuj zdefiniować 'reverse' w inny sposób, wypełniając następujące:' reverse [] = ...; reverse (x: xs) = ... 'i myśl o tym, że" odwrotnością pustej listy jest ... i odwrotnie do 'x' podanego z listą' xs' jest ... " – jberryman
Pamiętaj, że to ogólnie wątpliwe, aby uzyskać dostęp do list według indeksu. Są one specjalnie zaprojektowane, aby można je było łatwo dekonstruować, z elementu głowicy po elemencie, ale bardzo źle, gdy żądasz elementu w dowolnej pozycji. – leftaroundabout