SodiumでFunctional Reactive Programming (F#) --- 現在値の参照
現在値を参照しない例
Streamの入力があると値が100となる、初期値0のCellは以下のように記述できます。
let value = input |> Stream.mapTo 100 |> Stream.hold 0
現在値を参照する例
Streamの入力があると1ずつ増加する、初期値0のCellは以下のように記述できます。
loopWithNoCapturesを利用すると自分自身を参照できるようになります。
snapshotを利用すると、Streamの入力と、その時のCellの値から新しいStreamを作成できます。
let value = Cell.loopWithNoCaptures(fun value -> input |> Stream.mapTo 1 |> Stream.snapshot (+) value |> Stream.hold 0 )
アプリケーション例
上記をふまえてカウンタを作成します。
実装
DataContextは以下の記事のものを利用しています。
SodiumでFunctional Reactive Programming (F#) --- WPF連携 - 何でもプログラミング
F#でWPFを利用する方法は下記記事を参照してください。
F#でWPF --- ウィンドウ表示 - 何でもプログラミング
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Title="MainWindow" Height="100" Width="215"> <Grid> <Button Content="-" Command="{Binding Decrement}" HorizontalAlignment="Left" Margin="46,23,0,0" VerticalAlignment="Top" Width="25"/> <TextBlock Text="{Binding Count}" HorizontalAlignment="Left" Margin="97,25,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> <Button Content="+" Command="{Binding Increment}" HorizontalAlignment="Left" Margin="132,23,0,0" VerticalAlignment="Top" Width="25"/> </Grid> </Window>
F#
type Input = { Decrement : unit Stream Increment : unit Stream } type Output = { Count : int Cell } let createOutput input = let count = Cell.loopWithNoCaptures(fun count -> Stream.orElseAll [ input.Decrement |> Stream.mapTo -1 input.Increment |> Stream.mapTo 1 ] |> Stream.snapshot (+) count |> Stream.hold 0 ) { Count = count } [<STAThread>] [<EntryPoint>] let main argv = let window = Application.LoadComponent(Uri("MainWindow.xaml", UriKind.Relative)) :?> Window window.DataContext <- DataContext(createOutput) Application().Run(window) |> ignore 0