【F#】逆順パイプライン演算子

  • 2012.03.06 Tuesday
  • 20:08
 > Seq.fold (+) 0 (seq { 1 .. 100 });;
val it : int = 5050

> Seq.fold (+) 0 <| seq { 1 .. 100 };;
val it : int = 5050

逆順パイプライン演算子を使って評価順序を変更する例。なるほど!




> seq { 1 .. 100 };;
val it : seq<int> = seq [1; 2; 3; 4; ...]
> { 1 .. 100 };;
val it : seq<int> = seq [1; 2; 3; 4; ...]

そもそもseqって書かなくてのもいいのね・・・。

【F#】Seq.unfoldとは

  • 2012.03.05 Monday
  • 22:13
Seq.unfold関数を絵で表現してみた。





こんな感じ。

1.Seq.unfold関数は、シーケンスを生成する関数
評価した際は

seq [ result1, result2, result3 ... ]

となる。

2. Seq.unfold関数の第1引数は、一つの入力と2つの組のoption型を返す関数

絵では関数をで表現してみた。

stateNを引数としてが評価される。結果は、resultN1とstateN1。resultNはシーケンスの要素となる。stateN1は次の関数の引数となる。

3. Seq.unfold関数の第2引数は、最初の引数state0。 


感想
組ってすごいなー。
関連性のないもの、関連の表現しにくいものを、ほいっとかけちゃう。Some(resule, state)をC#を使ってクラスで表現使用としたとき、名前をどうつけようか途方に暮れてしまいます。

for文とかforeach文に使い慣れてくると、結局、その手続きできれいに記述できるコードを書こうと無意識に行動してるんだなーって気づかされました。C#にunfoldの実装をしてみた後の違和感といったら・・・。

【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??その2

  • 2012.03.03 Saturday
  • 23:10
----------------------------------------------------------------------------
【関連】
【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??
http://pro.art55.jp/?eid=1303926
【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??その2
http://pro.art55.jp/?eid=1303927
【C#】F#のSeq.unfold関数をC#で実装してみた。
http://pro.art55.jp/?eid=1303928
【C#】F#のSeq.unfold関数をC#で実装してみた。その2
http://pro.art55.jp/?eid=1303929
-----------------------------------------------------------------------------

【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??そ(http://pro.art55.jp/?eid=1303926)の続きです。

背伸びしてフィボナッチ数のシーケンスを求めたいと思います。
フィボナッチ数列は下記のように定義できるそうです(参照Wik)

式1: F_0 = 0
式2: F_1 = 1
式3: F_n2 = F_n + F_n1 (n>=0)
※_n1は下付のn+1、_n2は下付のn+2

(雑記)一般項の証明は高校でならったような気がしますが、完全に忘れていました。なんでルートが出てくるん??って、昔ならったとすれば、同じ事に2度驚いたことになります。

で、Seq.unfoldの第一引数の関数に当てはめてみたいと思います。

カレントの値がF_nならネクストの値はF_n1です。

式3はつまり二つ連続するフィボナッチ数を組とする引数をとると、そのFn1の次のフィボナッチ数が求められるということなので

F_n2 (F_n, F_n1) = F_n + F_n1

なので
カレントの状態(F_n, F_n1)を渡すとカレントの値がFnになり
カレントの状態(F_n, F_n1)を渡すとネクストの状態は(Fn1, Fn2)
(Fn1, Fn2)は(Fn1, Fn + Fn1)と書き換えることができます。

なのでフィボナッチ数列をシーケンスで表現すると

let fibonacciSequence = Seq.unfold (fun (f_n, f_n1) -> Some(f_n, (f_n1, f_n + f_n1))) (0, 1) 

となります。

コンソール出力させるコードも記述すると

let fibonacciSequence = Seq.unfold (fun (f_n, f_n1) -> Some(f_n, (f_n1, f_n + f_n1))) (0, 1) 
fibonacciSequence 
    |> Seq.takeWhile (fun number -> number <= 1000) 
    |> Seq.iter (printfn "%d")

で出力結果は

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987

オライリーに書かれてるコードと差異がありますが、なんとか自分で記述することができました。

【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??

  • 2012.03.03 Saturday
  • 22:08
----------------------------------------------------------------------------
【関連】
【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??
http://pro.art55.jp/?eid=1303926
【F#】Seq.unfoldは理解するのは難しいが・・・分かると簡単??その2
http://pro.art55.jp/?eid=1303927
【C#】F#のSeq.unfold関数をC#で実装してみた。
http://pro.art55.jp/?eid=1303928
-----------------------------------------------------------------------------

オライリーのプログラミングF#のP88にSeq.unfoldが紹介されているのですが、なんのこっちゃわからない。ということで、自分でシンプルなコードを書いてみようとしてみたもののコンパイルエー・・・コンパイルエラー・・・コンパイルエラー・・・

と、悪戦苦闘しました。何を勘違いしていたのか説明するのは難しいのですが、Seq.unfoldに対して押さえておくポイントは分かったので書き下します。

1.Seq.unfoldはシーケンスを生成する関数です。
これ重要です。List.mapなど何かのシーケンスから新しいシーケンスを生成するたぐいのものではありません。

2.第一引数は「カレントの状態」を渡すと「カレントの値」と「ネクストの状態」の組をオプション型で返す関数を用意しなければならない。
いい言葉がみつからなかったので、表現にこまっているのですが、
・カレントの状態が引数になり、カレントの値を求める
・カレントの状態が引数になり、ネクストの状態(つまり次の引数)を求める
これが組としてセットになっていて、続けられない場合はNoneを返す。
ということだと思います。

3. 第二引数は初期値
最初のカレントとなる値、つまり初期値って事ですね。

4. Seq.unfoldは漸化式で求められるシーケンスを得るための関数
と、いうことなんですね。

単純に0から始まる正の整数のシーケンスをコードで表してみたいと思います。

まず、カレントの状態からカレントの値とネクストの状態のoption型の組を求める関数を作成してみます。

> let getCurrentValueAndNextState currentState = Some(currentState, currentState + 1);;

val getCurrentValueAndNextState : int -> (int * int) option

Seq.unfoldでシーケンスを生成してみます。

> let numberSeq = Seq.unfold getCurrentValueAndNextState 0;;

val numberSeq : seq<int>

エラーになりません(笑)

とりあえず10個取り出して出力してみました。

> numberSeq |> Seq.take 10 |> Seq.iter (printfn "%d");;
0
1
2
3
4
5
6
7
8
9

なんかできてる!

【F#】seqはプル方式でlistはプッシュ方式 その3

  • 2012.03.03 Saturday
  • 09:16
【F#】seqはプル方式でlistはプッシュ方式 
【F#】seqはプル方式でlistはプッシュ方式 その2

上記の続きです。「seqはプル方式でlistはプッシュ方式」ってどういう意味なんだろう?正確な意味をとらえたいって思ってるわけですが、なかなか悩ましいです。「【F#】seqはプル方式でlistはプッシュ方式 その2」では絵で表現してみようと試みたのですが、どうも違う気がします。

という事で整理したいと思います。

・リストは事前に値が決定されている必要がある。
・シーケンスは事前に値が決定されておらず、引き出すときに値が決定する。

要は値が決定するタイミングの違いに関して言及しているものと思われるので、値の確定するタイミングに関して絵で表現するべきでは?と考え直してみました。


■リストの中の値が確定するタイミング
リストに対してPushした時に決定する。


■シーケンスの中の値が決定するタイミング
シーケンスに対してPullした時に決定する。


なので、「seqはプル方式でlistはプッシュ方式」といえる。


ということなのかな???

【F#】F#は絵を書くとイメージしやすい。

  • 2012.03.01 Thursday
  • 22:37
「 F#は絵を描くとイメージしやすい」・・・のではないか?って最近おもってます。

たとえばList.sumのイメージはこんな感じ


これを手続きで書こうとすると大変なんです。
変わっていく値を表現するとか・・・悩みます。
結局、処理が主体になって、何が目的なのかということが表現しにくくなります。

【F#】実践F# 関数型プログラミング入門(正誤表)

  • 2012.03.01 Thursday
  • 02:21
実践F# 関数型プログラミング入門(正誤表)

オライリーの正誤表を探してたら、偶然発見しました。



肝心のオライリーの方が見つからない・・・
http://www.oreilly.co.jp/books/9784873114668/
ここにあるような言い回しが書籍の中にかかれているんだけども・・・

【F#】seqはプル方式でlistはプッシュ方式 その2

  • 2012.02.29 Wednesday
  • 02:23
let collection = seq {
while true do
yield System.Console.ReadLine() }

collection |> Seq.takeWhile (fun item -> item <> "Z") |> Seq.iter (printfn "%s")
let list = collection |> Seq.takeWhile (fun item -> item <> "Z") |> Seq.toList
list |> List.iter (printfn "%s")


【F#】seqはプル方式でlistはプッシュ方式(http://pro.art55.jp/?eid=1303917)の続きなんですが、最後にこんなコードを書いて、

「やっぱりF#は絵で描いたらわかりやすくなるんじゃない?」

とおもったので書いてみました。


上がPullで下がPushです。パイプライン処理をベルトコンベアでイメージするとわかりやすいってセミナーか書籍か忘れましたが、紹介されていたと記憶していますが、強引にPushもPullもベルトコンベアモデルにあてはめるなら、その歯車をどこで回してるか?ってところが肝みたいですね。

個人的には自分が書いた絵の方がわかりやすい!と思いますが・・・(あえて苦笑でスルーしてください)

--------------------
(追記)
イメージを再考してみた結果、下記の方が正しいのではないかという結論に至りました。


-----------------
(追記)
再度考察しなおしました。

【F#】seqはプル方式でlistはプッシュ方式

  • 2012.02.28 Tuesday
  • 21:28
「プログラミングF#(O'REILLY)」の3章関数プログラミングp86の中でこう書かれています。

「シーケンスの場合には後付けで要素の値を決めることができます。(いわゆるプル方式です。)」

訳注には

「既知のの値を設定するリストはプッシュ方式ということができます。」



・・・・まったくイメージがわかない・・・どういうこと?


seqは、seqに対して、使う側が「くれ」と要求した分だけ引き取るからpull方式?
listは、listが用意した分だけを使う側が処理されるからpush方式?

--------------
(追記)
C#で書くとこんなイメージ?

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication17
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Begin Seq");
            IEnumerable<string> seq = GetSeq().TakeWhile(item => item != "Z");
            using (var it = seq.GetEnumerator())
            {
                while (it.MoveNext() /* 次の要素を「くれ」と要求、この時はじめて次の要素が評価される。 */)
                {
                    Console.WriteLine(it.Current);
                }
            }

            Console.WriteLine("Begin List");
            List<string> list = GetSeq().TakeWhile(item => item != "Z").ToList();
            using (var it = list.GetEnumerator())
            {
                while (it.MoveNext() /* 次の要素を「くれ」、すべての要素はすでに確定している */)
                {
                    Console.WriteLine(it.Current);
                }
            }
        }

        static IEnumerable<string> GetSeq()
        {
            while (true)
            {
                yield return Console.ReadLine();   
            }
        }
    }
}


-----------------
(追記2)
計画した個数を工場で生産して、お店に並べるのがPush方式
お店が注文とって工場に、何個つくれや!っていうのがPull方式


工場をseqやlistと見立てると
計画した個数をlistが用意して、後処理でなんか処理するのがPush方式
seqがあって、後処理でseqの要素が必要になったとき値を取得し、なんか処理するのがPush方式

って事なんだな。

---------------
(追記3)
F#でがんばって書いてみた。

let collection = seq { 
                    while true do
                        yield System.Console.ReadLine() }

collection |> Seq.takeWhile (fun item -> item <> "Z") |> Seq.iter (printfn "%s")
let list = collection |> Seq.takeWhile (fun item -> item <> "Z") |> Seq.toList
list |> List.iter (printfn "%s")

---------------
(追記4)
絵を描いて表現してみました。
【F#】seqはプル方式でlistはプッシュ方式 その2

再度考察しなおしました。
【F#】seqはプル方式でlistはプッシュ方式 その3

【F#】Reflectorで遊んでみた。

  • 2012.02.21 Tuesday
  • 23:05

そういえばReflectorってC#で作った実行ファイルを解析してF#に変換することってできるんじゃなかったけ?って思い出したので試してみました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication12
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<int> { 1, 2, 3, 4, 5 };
            var result = new List<int>();
            foreach (int i in list)
            {
                result.Add(i);
            }

            foreach (int i in result)
            {
                Console.WriteLine(i);
            }
        }
    }
}

 


let rec Main args  =
    let temporary1 =
        let list =
        let result =
        let temporary2 = (* Statement type not handled *)
        match temporary2 with
        | Some _ as x -> x
        | None ->
            let temporary3 = (* Statement type not handled *)
            temporary3
        match temporary1 with
        | Some _ -> failwith "Expected non-unit return"
        | None -> ()
・・・穴あき問題か!?ちなみにVB.NETはこんな感じ


Friend Class Program
    ' Methods
    Private Shared Sub Main(ByVal args As String())
        Dim list As New List(Of Integer) From { 1, 2, 3, 4, 5 }
        Dim result As New List(Of Integer)
        Dim i As Integer
        For Each i In list
            result.Add(i)
        Next
        Dim i As Integer
        For Each i In result
            Console.WriteLine(i)
        Next
    End Sub

End Class
 VB.NETは全く無学だけど、なんとなくできてるような気がする。

calendar

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
30      
<< September 2018 >>

あわせて読みたい

あわせて読みたいブログパーツ

selected entries

categories

archives

recent comment

  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    art55 (05/22)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    分解大好き (05/18)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/04)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    Gen (02/04)
  • 【キーボード】RealForce が壊れて帰ってきた。
    art55 (04/29)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/23)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    かるあ (02/22)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    art55 (01/16)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    karuakun (01/16)
  • 【NetOffice】【Excel】死なないExcelプロセスをKillする。
    art55 (12/05)

recent trackback

recommend

recommend

recommend

C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION)
C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION) (JUGEMレビュー »)
Sasha Goldshtein,Dima Zurbalev,Ido Flatow,サシャ・ゴルドシュタイン,ディマ・ズルバレフ,イド・フラトー

recommend

ろんりと集合
ろんりと集合 (JUGEMレビュー »)
中内 伸光
とてもわかりやすいです。

recommend

recommend

シャノン・ノイマン・ディジタル世界
シャノン・ノイマン・ディジタル世界 (JUGEMレビュー »)
市川 忠男
4章がリレーショナルデータベースな内容になってます。ページ数があまりありませんが、ポイントがものすごく的確にまとまっていて、感動します。

recommend

recommend

東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS
東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS (JUGEMレビュー »)

テンキーレス、静音のRealForce91UBK-S。スコスコ感がたまらなく気持ちいいです。家と会社で2台持ってます。

recommend

recommend

プログラミング.NET Framework 第4版 (プログラミングシリーズ)
プログラミング.NET Framework 第4版 (プログラミングシリーズ) (JUGEMレビュー »)
Jeffrey Richter
発売予定美 2013年10月10日。.NET Frameworkとお付き合いする人のバイブルですね。

recommend

recommend

キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。

recommend

Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM