Dies ist ein literarischer Haskell Beitrag. Speichern Sie es einfach als "ChurchList.lhs", um es auszuführen.Effizienterer Schwanz der Kirche codierte Liste
> {-# LANGUAGE Rank2Types #-}
Eine Church-codierte Liste ist eine Möglichkeit, eine Liste über eine Funktion darzustellen. Es ähnelt sowohl dem Folding als auch dem Fortsetzungsstil.
> newtype ChurchList a = CList {runCList :: forall r. (a -> r -> r) -> r -> r}
Zur Veranschaulichung, wie diese zu einer Liste entspricht, ist hier ein O (n) Isomorphismus
> fromList :: [a] -> ChurchList a
> fromList xs = CList $ \cons empty -> foldr cons empty xs
> toList :: ChurchList a -> [a]
> toList cl = runCList cl (:) []
> instance Show a => Show (ChurchList a) where
> show cl = "fromList " ++ show (toList cl)
Diese Dinge haben eine gute Leistung charecteristics.
> singleton :: a -> ChurchList a -- O(1)
> singleton a = CList $ \cons empty -> a `cons` empty
> append :: ChurchList a -> ChurchList a -> ChurchList a -- O(1)!!! This also means cons and snoc are O(1)
> append cl1 cl2 = CList $ \cons empty -> runCList cl1 cons (runCList cl2 cons empty)
> concatCl :: ChurchList (ChurchList a) -> ChurchList a -- O(n)
> concatCl clcl = CList $ \cons empty -> runCList clcl (\cl r -> runCList cl cons r) empty
> headCl :: ChurchList a -> Maybe a -- O(1)
> headCl cl = runCList cl (\a _ -> Just a) Nothing
Jetzt kommt das Problem mit tail
.
> tailClbad :: ChurchList a -> Maybe (ChurchList a) --O(n)?!!
> tailClbad cl = (fmap snd) $ runCList cl
>
> (\a r -> Just (a, case r of
> Nothing -> CList $ \cons empty -> empty
> Just (s,t) -> append (singleton s) t)) --Cons
>
> Nothing --Empty
Im Wesentlichen was meine Implementierung tut, ist die Liste in Kopf und Schwanz aufgeteilt. Cons ersetzt den Kopf und fügt den alten Kopf an den Schwanz an. Dies ist ziemlich ineffizient. Es scheint, dass Church Lists im Allgemeinen beim Aufspalten ineffizient sind.
Ich hoffe, dass ich falsch liege. Gibt es eine Implementierung von tailCl
, die besser ist als O (n) (vorzugsweise O (1)).
Wie von Oleg Kiselyov [[hervorgehoben] (https://mail.haskell.org/pipermail/haskell-cafe/2012-September/103493.html), ist dies tatsächlich Boehm-Berarducci Codierung. Der Artikel, den er in der Mail verlinkt, ist ziemlich interessant. –