2017-06-11 1 views
1

Ich habe mit einigen f # Parsern und einige Streaming-Software gearbeitet und ich finde mich damit Muster mehr und mehr. Ich finde es eine natürliche Alternative zu Sequenzen und es hat einige natürliche Vorteile. Hier sind einige Beispielfunktionen, die den Typ verwenden.Gibt es einen Namen für dieses Muster "Typ 'eine gefalteteSequenz = leer | Wert von' a * (Einheit -> 'eine gefaltete Sequenz)"

type foldedSequence<'a> = 
    | Empty 
    | Value of ' a * (unit -> 'a foldedSequence) 

let rec createFoldedSequence fn state = 
    match fn state with 
    | None -> Empty 
    | Some(value, nextState) -> 
     Value(value, (fun() -> unfold fn nextState)) 

let rec filter predicate = 
    function 
    | Empty -> Empty 
    | Value(value, nextValue) -> 
     let next() = filter predicate(nextValue()) 
     if predicate value then Value(value, next) 
     else next() 

let toSeq<'t> = 
    Seq.unfold<'t foldedSequence, 't>(function 
     | Empty -> None 
     | Value(value, nextValue) -> Some(value, nextValue())) 

Es ist sehr hilfreich gewesen wäre ich gerne wissen, ob es einen Namen hat, so kann ich es einige Tipps und Tricks Forschung

+0

FWIW „predecate“ sollte wohl „Prädikat“ sein;) –

+0

welche Art werden über Sie fragen, der eine im Titel oder der andere im Fragenkörper? das letzte ist ein Strom, der entweder leer ist, oder ein Paar, das den gegenwärtigen Wert und die Funktion hält, um den folgenden Strom zu produzieren. –

+0

Sorry, dass ich mich in der Kopfzeile vertippt habe, frage ich nach dem Stream 'type foldedSequence <'a> = Empty | Wert von 'a * (Einheit ->' a foldedSequence) ' –

Antwort

3

Um zu den vorhandenen Antworten hinzuzufügen, denke ich, dass Haskellers eine verallgemeinerte Version dieses a list monad transformer nennen könnte. Die Idee ist, dass Ihre Typdefinition fast wie normale F # list aussieht, außer dass es einen zusätzlichen Aspekt gibt. Sie können sich vorstellen, schreibe dies als:

type ListTransformer<'T> = 
    | Empty 
    | Value of 'T * M<ListTransformer<'T>> 

Durch gezielte M liefert, können Sie eine Reihe von Dingen definieren:

  • M<'T> = 'T gibt Ihnen die gewöhnlichen F # Listart
  • M<'T> = unit -> 'T Sie Ihre Sequenz gibt, dass kann lazy
  • M<'T> = Lazy<'T> ausgewertet werden gibt Ihnen LazyList (die bereits ausgewertete Elemente zwischenspeichert)
  • M<'T> = Async<'T> gibt Ihnen asynchronous sequences

Es ist auch, dass sich LazyTransformer<'T> nicht eine verzögerte/faul/Asynchron-Wert in dieser Definition erwähnenswert. Dies kann in einigen Fällen zu Problemen führen - z. wenn Sie einige Asynchron-Betrieb durchführen müssen, um zu entscheiden, ob der Strom leer ist - und so eine bessere Definition ist:

type ListTransformer<'T> = M<ListTransformerInner<'T>> 
and ListTransformerInner<'T> = 
    | Empty 
    | Value of 'T * ListTransformer<'T> 
+0

Danke! Das war genau das, was ich suchte. Ich bin immer noch neu in funktionalen Typsystemen und habe nie daran gedacht, ein generisches Monoid zu verwenden, um den Fortsetzungswert zu umbrechen. –

+0

@ThomasDebries Glücklich das half! Das kann man nicht ganz allgemein in F # tun, da es keine Möglichkeit gibt, den Typ durch einen anderen parametrisierten Typ zu parametrisieren (zB generic über 'M'), aber ich denke, dass dies immer noch als allgemeines Designmuster nützlich ist (plus, denke ich Dies zu behandeln, genauso wie ein Designmuster, lässt Sie darüber nachdenken, es für den spezifischen Anwendungsfall, den Sie im Sinn haben, gut zu entwerfen). –

1

Ihre Art ist in der Nähe, wie ein n iteratee würde definiert werden, und da Sie bereits Streaming erwähnen, könnte dies das Konzept sein, nach dem Sie suchen.

Iteratee IO ist ein Ansatz für Lazy IO, umrissen von Oleg Kiselyov. Neben Haskell existieren Implementierungen für die wichtigsten funktionalen Sprachen, einschließlich F # (als Teil von FSharpx.Extras). Diese

ist wie FSharpx definiert eine Iteratee:

type Iteratee<'Chunk,'T> = 
    | Done of 'T * Stream<'Chunk> 
    | Error of exn 
    | Continue of (Stream<'Chunk> -> Iteratee<'Chunk,'T>) 

Siehe auch dieses Blog-Post: Iteratee in F# - part 1. Beachten Sie, dass es keinen Teil 2 zu geben scheint.

Verwandte Themen