2012-05-31 4 views
15

Lassen Sie uns sagen, ich habe diese Funktion: (Haskell Syntax)Berechnung der Arbeit von f getan x = (x, x)

f x = (x,x) 

Was ist die Arbeit (Berechnungsmenge) durch die Funktion ausgeführt?

Zuerst dachte ich, es sei offensichtlich konstant, aber was ist, wenn der Typ von x nicht endlich ist, was bedeutet, dass x eine beliebige Menge an Speicher aufnehmen kann? Man müsste die Arbeit berücksichtigen, die durch das Kopieren von x gemacht wurde, oder?

Dies führte zu der Annahme, dass die von der Funktion geleistete Arbeit in der Größe der Eingabe tatsächlich linear ist.

Diese für sich nicht Hausaufgaben, aber kam, als ich die Arbeit von der Funktion getan definieren musste:

f x = [x] 

, die ein ähnliches Problem hat, glaube ich.

+0

gute Frage für http://cs.stackexchange.com/ – FlavorScape

+0

Sollte ich es verschieben? (Vorausgesetzt, ich kann, ich bin nicht wirklich vertraut mit der Website) – Guido

+1

@Guido Sie können es nicht verschieben, obwohl es nicht möglich ist, es an das Ziel zu verschieben, denke ich, dass es auch passt. IMHO ist es das Beste, es hier zu lassen. – fuz

Antwort

33

Sehr informell hängt die geleistete Arbeit von der operativen Semantik Ihrer Sprache ab. Haskell, na ja, es ist faul, so zahlen Sie nur konstante Faktoren:

  • Push-Zeiger auf x auf dem Stapel
  • für (,)
  • gelten (,) auf ihre Argumente
  • Rückkehr ein einen Haufen Zelle zuweisen Zeiger auf die Heap-Zelle

Fertig. O (1) funktionieren, wenn der Anrufer das Ergebnis von f betrachtet.

Jetzt werden Sie weitere Auswertung auslösen, wenn Sie in die (,) schauen - und diese Arbeit ist abhängig von der Arbeit zu bewerten x selbst. Da in Haskell die Referenzen auf x geteilt werden, werten Sie diese nur einmal aus.

Also die Arbeit in Haskell ist O (Arbeit von x), wenn Sie das Ergebnis vollständig auswerten. Ihre Funktion f fügt nur konstante Faktoren hinzu.

+7

Um weiter zu verdeutlichen: '(,)' in Haskell ist ein * boxed * Tupel, was bedeutet, dass es ein Konstrukt ist, das nur Zeiger hält. Wenn Sie eine Sprache haben, in der '(,)' ein * unboxed * Tupel erzeugt, dann wird es zusätzliche Arbeit erfordern, 'x' in beide Slots zu klonen, wenn' x' größer ist als ein Zeiger und die Menge an Arbeit skaliert mit der Größe von 'x'. [GHC stellt ungeboxte Tupel zur Verfügung (http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/primitives.html#unboxed-tuples) '(#, #)' mit verschiedenen Einschränkungen. –

1

Chris Okasaki hat eine wunderbare Methode, die Arbeit zu bestimmen, die geladen wird, um zu funktionieren, wenn etwas (oder totale) Faulheit eingeführt wird. Ich glaube, es ist in seinem Artikel über rein funktionale Datenstrukturen. Ich weiß, dass es in der Buchversion ist - ich habe diesen Teil des Buches letzten Monat gelesen. Grundsätzlich berechnen Sie einen konstanten Faktor für das Versprechen/Thunk erstellt, laden Sie nichts für die Bewertung der übergebenen Versprechen/Thunks (angenommen, sie wurden bereits gezwungen/sind in normaler Form [nicht nur WHNF]). Das ist eine Unterschätzung. Wenn Sie eine überschätzen Ladung wollen, auch die Kosten der Forcierung/Umwandlung in Normalform jedes Versprechen/Thunk von der Funktion erstellt. Zumindest erinnere ich mich daran in meinem extrem müden Zustand.

Schauen Sie in Okasaki: http://www.westpoint.edu/eecs/SitePages/Chris%20Okasaki.aspx#thesis - Ich schwöre die These verwendet werden herunterladbar.

+0

In Haskell scheint ein polymorphes Argument Okasakis Methode zu entkräften. (1) Vermeide es wenn möglich. (2) Ich habe das nicht vollständig analysiert, es ist nur eine Intuition. –