ストリーム (遅延リスト) とモナドの間に違いはありますか? 技術的な実装からではなく、概念的および数学的観点から。
あるいは、2 つの固有の 1 対 1 の対応関係は存在しますか?
より正確には、ストリームとしては、Scheme 言語のSRFI-41からの「偶数ストリーム」を意味します。
モナドとは別のカテゴリーですか?もしそうなら、それはどのカテゴリーですか?
「偶数ストリーム」は、モナドのような副作用の制御を保証できますか?
ストリーム (遅延リスト) とモナドの間に違いはありますか? 技術的な実装からではなく、概念的および数学的観点から。
あるいは、2 つの固有の 1 対 1 の対応関係は存在しますか?
より正確には、ストリームとしては、Scheme 言語のSRFI-41からの「偶数ストリーム」を意味します。
モナドとは別のカテゴリーですか?もしそうなら、それはどのカテゴリーですか?
「偶数ストリーム」は、モナドのような副作用の制御を保証できますか?
Salil が既に述べたように、この 2 つは異なる概念です。
ストリームは (潜在的に無限の) 値のリストであり、通常は遅延方式で計算されます。つまり、要求されたときに値を計算する何らかの方法のみを格納します。モナドをまったく含まない多くの例があります。
(define integers (cons-stream 1 (stream-map (lambda (x) (+ x 1)) integers))
有限の事前計算されたリストをストリームと見なすことも非常に便利です。これは、(潜在的または必然的に) 有限の遅延ストリームを使用できる場所ならどこでも使用できるためです。
したがって、ストリームとはnext: streamType -> (valueType streamType)
、次の値と残りのストリームを取得する操作を持つものです。
一方、モナドはデータ構造ではなく、個々のコマンドを組み合わせてソースコードを記述する方法です。
おそらく最も単純な有用な例は「多分モナド」です – それがSchemeでどのように見えるかはわかりませんが、申し訳ありませんが、アイデアは: 計算のリストと(f g h)
入力が与えられた場合x
、計算を順番に実行します。が与えられた場合(f (g (h x)))
、各関数は正常に失敗するようにします。g
が返された場合はnil
、 を呼び出さず(f nil)
、代わりにnil
すぐに戻ります。
もちろん、この 2 つをさまざまな便利な方法で組み合わせて、モナドを使用してストリーム値を計算したり、モナドでの関数型プログラミングの期待に厳密に従っていない I/O ストリームのようなストリームの使用をカプセル化することができます (コードがモナドにストリームの以前の状態への参照)、しかしそれらは完全に異なる目的を果たします。抽象化レイヤーについて考えてみてください (カバーを閉じて、内部を見ないでください): 関数に適用されるモナドは、関数を提供します。一方、ストリームは高等関数ではなく、値のリストです。
明らかに、モナドによって定義された (または視点によってはモナドから返された) 関数は、ストリームの実装である可能性があり、ストリームから抽出された値はモナドである可能性もあります。しかし、上で見たように、ストリームとはまったく異なるものを実装するモナドがあります。モナドとして実装されていないストリームがあるかどうかは、おそらくその用語を正確に何に使用するかに依存します。正直に言うと、無限ストリームがモナドとして適切に機能するかどうかは現時点ではわかりません。有限リストは明らかにそうです。