2017-06-11 6 views
1

私はいくつかのf#パーサーといくつかのストリーミングソフトウェアを使っています。より多くのパターン。私はそれが配列の自然な代替物であることがわかり、いくつかの自然な利点があります。 は、この型を使用する関数の例です。 「パワーパック」にあった。これは、LazyListように聞こえる私はそれが名前を持っている場合ので、私はそれこのパターンの名前はありますか?a型式a a foldedSequence = Empty | 'a *(unit - > a foldedSequence)'の値

+0

FWIW、「predecate」おそらく「述語」である必要があります。)について、あなたは求めているタイプ –

+0

、問題の本文の中のタイトルのものかもう一つのものか?その最後のストリームは空であるストリーム、または現在の値を保持するペアと次のストリームを生成する関数です。 –

+0

申し訳ありませんヘッダーでミスタイプしました。ストリームについて質問しています。 'type foldedSequence <'a> = Empty | 'a *(unit - >' a foldedSequence) 'の値 –

答えて

3

既存の回答に追加するには、私はハスケラーはこれの一般化されたバージョンを呼び出すかもしれないこのa list monad transformer。その考え方は、あなたの型定義は通常のF#listのように見えますが、それにはいくつかの追加の側面があります。

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

特定Mを供給することにより、あなたは物事の数を定義することができます:あなたは、これはと書いて想像することができます

  • M<'T> = 'Tはあなたに
  • M<'T> = unit -> 'Tはあなたの順序を与える通常のF#のリストタイプを与えること遅く評価することができます
  • M<'T> = Lazy<'T>はあなたにLazyListを与えます(既に評価された要素をキャッシュします)
  • M<'T> = Async<'T>はまた、この定義にLazyTransformer<'T>が遅れ/怠惰/非同期値そのものではないことは注目に値する

あなたにasynchronous sequencesを与えます。これは、場合によっては問題を引き起こす可能性があります。あなたは、ストリームが空であるかどうかを決定するためにいくつかの非同期操作を実行する必要がある場合 - ので、より良い定義は次のとおりです。

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

ありがとう!これはまさに私が後にしたものでした。私はまだ機能型システムの新しさと私は継続的な値を包むために一般的なモノイドを使用することを考えたことはありません。 –

+0

@ThomasDevriesハッピーこれが助け! F#ではこれを一般的に行うことはできません。これは、別のパラメータ化された型で型をパラメータ化する方法がないためです(これはMを使って一般化します)。しかし、これはまだ一般的な設計パターンとしては便利です。これをデザインパターンと見なすことで、あなたが念頭に置いている特定のユースケースに対してうまく設計することが難しくなります)。 –

1

のためにいくつかのヒントやトリックを研究することができます知っていただきたいと思い非常に参考にされています

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())) 

http://fsprojects.github.io/FSharpx.Collections/reference/fsharpx-collections-lazylist-1.html

https://github.com/fsprojects/FSharpx.Collections/blob/master/src/FSharpx.Collections/LazyList.fs

1

あなたのタイプはどのように近いです:私は今ここに住んでいると思いますiterateeが定義され、すでにストリーミングについて言及しているので、これはあなたが探しているコンセプトかもしれません。

Iteratee IOは、Oleg Kiselyovで概説された遅延IOへのアプローチです。ハスケルとは別に、F#(FSharpx.Extrasの一部として)を含む主要な関数言語の実装が存在します。

これはFSharpxはIterateeを定義する方法である:

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

は、このブログの記事も参照してください:Iteratee in F# - part 1。注意してください2分であるように注意してください。

関連する問題