2014-03-27 2 views
5

Lange Rede kurzer Sinn, ich mit diesem lustigen Funktion kam gesetzt, die eine Funktion übernimmt, f: ‚k ->‚v, ein gewählter Wert, k:‘ k, ein ausgewähltes Ergebnis v: ‚v verwendet f als Grundlage für eine neue Funktion g:‘ k -> ‚v, die genau die gleiche wie f ist, mit Ausnahme, dass es nun gilt, dass , gk = v.F # - Die Behandlung einer Funktion wie eine Karte

Hier ist die (ziemlich einfach) F # Code, den ich um geschrieben zu machen:

let set : ('k -> 'v) -> 'k -> 'v -> 'k -> 'v = 
    fun f k v x -> 
     if x = k then v else f x 

Meine Fragen sind:

Enthält diese Funktion keine Probleme aufwerfen?

Ich könnte eine wiederholte Verwendung der Funktion vorstellen, wie dieser

let kvs : (int * int) List = ... // A very long list of random int pairs. 
List.fold (fun f (k,v) -> set f k v) id kvs 

beginnen würde, eine lange Liste von Funktionen auf dem Heap aufzubauen. Ist das etwas, worüber man sich Sorgen machen muss?

Gibt es einen besseren Weg, dies zu tun, während immer noch der Typ?

Ich meine, ich konnte tun Sachen wie eine Art Konstrukt für die ursprüngliche Funktion zu halten, f, eine Karte, auf der Karte Schlüssel-Wert-Paare Einstellung und Überprüfung der Karte zunächst die Funktion zweiten , wenn ich Schlüssel verwende, um Werte zu erhalten, aber das interessiert mich hier nicht - was interessiert mich daran, eine Funktion zu haben, um ein einzelnes Ergebnis für einen gegebenen Wert für eine gegebene Funktion zu "modifizieren".

Antwort

5

Mögliche Probleme:

  1. Die set -modifizierte Funktion Raum entweicht, wenn Sie den gleichen Wert zweimal außer Kraft setzen:

    let huge_object = ... 
    let small_object = ... 
    
    let f0 = set f 0 huge_object 
    let f1 = set f0 0 small_object 
    

    Auch wenn es nie die Ausgabe von f1 sein kann, kann huge_object nicht sein Müll gesammelt bis f1 kann: huge_object wird durch f0 verwiesen, die wiederum durch die f1 verwiesen wird.

  2. Die set -modifizierte Funktion hat einen linearen Overhead in der Anzahl von set Operationen, die darauf angewendet werden.

Ich weiß nicht, ob diese tatsächlichen Probleme für die vorgesehene Anwendung sind.

Wenn Sie möchten, dass set genau den Typ ('k -> 'v) -> 'k -> 'v -> 'k -> 'v haben, dann sehe ich keinen besseren Weg (*). Die naheliegende Idee wäre, eine "Modifikationstabelle" von Funktionen zu haben, die Sie bereits modifiziert haben, und dann set in dieser Tabelle nach f suchen.Aber Funktionstypen lassen keine Gleichheitsprüfung zu, so dass Sie f nicht mit den Funktionen vergleichen können, die Ihrer Modifizierungstabelle bekannt sind.

(*) Reflexion nicht zu widerstehen.

+0

Sie erwähnen Reflexion. Könntest du ein bisschen mehr darüber sprechen, wie das genutzt werden könnte? Also, was ist, wenn der Typ ** 'k ** eine einfache diskriminierte Union ist? – phaz

+0

Es macht keinen Unterschied "k" ist ein bekannter Typ "t". Sie würden dann Funktionen '(t -> 'v)' betrachten, aber _no_ Funktionstyp hat Gleichheit, also auch nicht diese. (Es ist ein bekanntes Ergebnis in der Informatik, dass es im Allgemeinen unmöglich ist zu bestimmen, ob zwei Funktionen gleich sind, d. H. Dieselbe Ausgabe für dieselbe Eingabe erzeugen.) –

+0

Wrt. Reflexion, ich stelle mir vor, Sie könnten Reflektion verwenden, um sich den Verweis auf die Laufzeitdarstellung der Funktion "k -> 'v" anzueignen. Das kann man für Gleichheit vergleichen und so eine Karte einfügen. –

Verwandte Themen