らくがき

2008/03/30

[F#] seqリストで ”指定した条件の直前まで” 抜き出すにはどうするの?

コード:
let takeUntil p (s : #seq<_>) =
  seq {
        let enum = s.GetEnumerator() in
        while enum.MoveNext() && not (p enum.Current) do
            yield enum.Current 
        done
      }
使用例:
let even_choose i = Seq.choose (fun x -> if (x &&& 1) = 0 then Some(x) else None) i

{1..10} |> even_choose |> takeUntil (fun x -> x > 6) |> Seq.fold ( + ) 0;;
結果:
val it : int = 12
{1..10} -> [1;2;3;4;5;6;7;8;9;10]  // リスト作成
even_choose -> [2;4;6;8;10]        // 偶数のみ選択
takeUntil -> [2;4;6]               // "6より大きい数が現れるまで" のリストをGet
Seq.fold -> 12                     // リストを合計 シチャイマス
 

Labels:

2008/03/29

ExcelでC#やVBやF#を利用する

"ExcelDna"(http://exceldna.typepad.com/) ExcelのセルにてC#/VB/F#で書いた関数を利用できるようになる DLLの関数を利用する場合は、.NETの言語であればなんでもいいみたい ".xll"と".dna"ファイルが対になって動作するようになっているので "test1.xll" と "test1.dna" のように名前部分を同じにする ".xll"ファイルは、ZIPに同梱されている"ExcelDna.xll"ファイルをリネームして使う C#で書いた関数を利用する場合 [test1.dna]
<DnaLibrary Language="CS">
  <![CDATA[
     using ExcelDna.Integration;
   
     public class MyFunctions
     {
         [ExcelFunction(Description="Joins a string to a number", Category="Useful functions")]
         public static string JoinThem(string str, double val)
         {
             return str + val;
         }
     }
  ]]>
</DnaLibrary>
F#で書いた関数を利用する場合
<DnaLibrary Language="Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider, FSharp.Compiler.CodeDom, Version=1.9.3.14, Culture=neutral, PublicKeyToken=a19089b1c74d0809">

      let sayhello () = "Hello from F#"
      let add x y = x + y

</DnaLibrary>
"FSharp.Compiler.CodeDom.dll"のVersionとPublicKeyTokenを合わせる

2008/03/26

[F#] 開発者との距離が近い

hubFSとかでのF#開発陣との距離の近さに改めて感心・感動 いい感じだゼ  

Labels:

[Silverlight 2.0] Deep Zoom デモ

これいいねー 平面で全体をざっと眺めて、気になる箇所をズームアップ! さらに気になる箇所をズームアップ! またまたズームアップ! あれ? そこどうなってんの? ズームアップ! Webマガジンとかでこんな形式とったら、おもしろそう

2008/03/23

[F#] 約log2n回の再帰呼び出しでべき乗(累乗)を計算する

29の場合は、次のように表すことができる これを下から上へ辿ると 内側から計算すると n が偶数のときには以下が成り立つ (res : 計算結果) n が奇数のときには以下が成り立つ n=9 を2進数で表すと 1001 2進数の場合は、最下位ビットが1だと奇数なので、それを調べて処理分けしています。
let pow7 (x:bignum) n =
  let rec poww d = 
    if d = 1 then
      x
    else
      let res = poww (d >>> 1) in
      if (d &&& 1) = 0 then
        (res * res)
      else
        (res * res * x)
  in
  poww n
実行結果:
> pow7 2N 9;;
val it : bignum = 512N
 

Labels:

2008/03/22

[F#] 動的に数値型Interfaceを対応付けて関数を動かす

GetNumericAssociation なるもので動的に数値型Interfaceと対応付けられるみたい (http://cs.hubfs.net/forums/thread/3129.aspx) コード:
#light
open Math
open Math.GlobalAssociations

let Add (n1:'a) (n2:'a) =
    let tn : INumeric<'a> = GetNumericAssociation<'a>()
    tn.Add(n1, n2)
結果は次のように色々な数値型で動作させることが可能
Add 1 2
> val it : int = 3

Add 1. 2.
> val it : float = 3.0

Add 1L 2L
> val it : int64 = 3L

Add 1.f 2.f
> val it : float32 = 3.0f
デフォルトで float, int32, int64, bigint, float32, Complex, bignum が使えて、 他の型も登録することで選択肢に加えることができるんだって。 Add を他の関数で使うとこれまた同じ効果を得られる
let MyGenFunc (n1:'a) (n2:'a) (n3:'a) =
    (Add (Add (Add n1 n2) (Add n1 n3)) (Add n2 n3))
結果:
MyGenFunc 1 2 3
> val it : int = 12

MyGenFunc 1. 2. 3.
> val it : float = 12.0
パフォーマンスを気にする場合は、ひとつの関数定義の中にすべてを含めてしまい、
let MyGenFunc (n1:'a) (n2:'a) (n3:'a) =
    let tn : INumeric<'a> = GetNumericAssociation()
    let inline (+) (n1:'a) (n2:'a) = tn.Add(n1, n2)
    ((n1 + n2) + (n1 + n3) + (n2 + n3))
演算子を適切に定義することで可読性を高めることもできる らしい! 他の例としてはこんなの(http://cs.hubfs.net/forums/thread/3823.aspx
let sumList (data:'a list) =
  // get the F# 'INumeric' interface implementation for a type 'a
  let num = GetNumericAssociation<'a>()
  data |> List.fold_left (fun a b -> num.Add(a,b)) num.Zero;;

// sumList [1; 2; 3; 4; 5] ... returns 15
// sumList [1.1; 2.2; 3.3; 4.4; 5.5] ... returns 16.5
 

Labels:

2008/03/19

[F#] 重複を持たない組合せ(nCm)

こんな感じかな? 数学音痴なので基本式まんまです(^-^; コード:
let Combination n m =
  let rec CC n m =
    if m = 0 then
      1
    else 
      let i = CC (n - 1) (m - 1) in
        (n * i / m)
  in
  let i = CC n m in
    i;;
10 C 5 の場合:
Combination 10 5
  CC 10 5
    CC 9 4
      CC 8 3
        CC 7 2
          CC 6 1
            CC 5 0
            = 1 <-- i
          = 6 * 1 / 1 = 6
        = 7 * 6 / 2 = 21
      = 8 * 21 / 3 = 56
    = 9 * 56 / 4 = 126
  = 10 * 126 / 5 = 252
= 252
必ず割り切れるという性質を利用して、毎回割っています。
2008/03/19 - 末尾再帰的に書くとこうだ!
コード:
let Combination (n, m) =
  let rec CC (i, j, res) =
    if j > m then
      res
    else
      CC ((i + 1), (j + 1), (i * res / j))
  in
  CC ((n - m + 1), 1, 1);;
まちがいない!  

Labels:

2008/03/17

hubFS

F# の活発なコミュニティ たぶん、ここで質問すればほとんどの答えを得られるんじゃないかな  

Labels:

[F#] Unicode文字を関数名や引数に使用可能!

C# と同じようにUnicode文字を関数名や引数に使えるみたい コード:
let ほげほげ あふん = printfn "%s" あふん

ほげほげ "表示"
結果:
val ほげほげ : string -> unit

表示
日本語で書けると便利なときもあるよね  

Labels:

[F#] ネストしたリストをフラットにする

ネストしたリストをフラットにするコード
type 'a tree =
   | E of 'a   // Element
   | N of 'a tree list // Node

let rec flattenTree (t:'a tree) : 'a list =
   match t with
   | E e -> [e]
   | N n -> List.flatten(List.map flattenTree n)
使用例:
let t1 = N [ E 1; N [E 2; E 3]; E 4 ]
flattenTree t1
flattenTree (N [ E "a"; N [ E "b"; E "c"]; E "d" ] )
結果:
> val it : int tree = N [E 1; N [E 2; E 3]; E 4]
> val it : int list = [1; 2; 3; 4]
> val it : string list = ["a"; "b"; "c"; "d"]
ふむふむ・・・なんとなくおk!  

Labels:

2008/03/16

HTMLで半角空白や改行を含んだコピペを有効にする

HTMLで半角空白や改行を含んだコピペを有効にするには、<pre>タグを使えばOK もしくはCSSの white-space:pre でもOK ただし、<pre>タグの中の改行を<br>タグで表しているとブラウザでは改行されているように見えるけど コピペすると<br>タグは改行に変換されないので、一行に連なった状態になってしまう。
この状態が見られる有名どころは、Hotmail
Hotmail のメール本文をコピペすると、すべて一行になっちゃうので
<br>タグによる改行をしてるみたい
他のタグの場合は、コピペの時に<br>タグが改行に変換されるんだけどね <pre>タグの中で<br>タグが有効なら、改行に変換してくれてもいいのにw (FireFox は<br>タグを改行に変換してくれるみたい! 素晴らしい!) Bloggerでは、設定のフォーマットのところにある「改行の変換」機能がONになっていると 入力した改行はすべて<br>タグに変換されてしまうので<pre>タグを活かすにはOFFにする必要があります。 そうすると、面倒になるのが<pre>タグ以外のとき改行をするのに手動で<br>タグを入力しないといけなくなること。 これを回避するには、記事自体を<pre>タグで括ってしまえばOK テンプレートで次の記述を探し
<p><$BlogItemBody$></p>
次のように書き換える
<p><pre><$BlogItemBody$></pre></p>

2008/03/12

#light は要注意

いろんなサンプルに「#light」って記述されているけど、これ、かなりのクセモノかも。 「#light」ありの場合は、変数の同時束縛ができないみたい
let x = 1 and y = 2   // Syntax error
「#light」なしの場合は、普通にOK
let x = 1 and y = 2
"in" とか書かなくていいからよさげ?と思っていたのも束の間 見事にはまりました 玄人から言わせれば 「同時束縛なんぞ 使う機会ない」 ってことかな? それか、別の記述方法があるのか… ナゾナゾ
2008/03/13 - #light 慣れれば素敵かも?
別の記述方法があった!
let x = expr
and y = expr
expr
こんな感じに let と並べないとダメなんだって。
let x = 1
and y = 2
x + y
とすると、#light なしでこう書けるものは
let gg =
  let x = 2 in 
  let y = 3 in
  (let y = x and x = y + 2 in x * y) + y
#light ありだとこんな感じ?
#light

let gg = 
  let x = 2  
  let y = 3 
  (let y = x
   and x = y + 2 
   x * y) + y
同時束縛のときは”並べないとダメ!”とか決められると誰が書いてもこの書式になるわけで ソースを見るときは楽かもしれない! 他にも結構決められてるみたいだから、「書き方おかしいぜ」って言われたらマニュアル要チェックや  

Labels:

2008/03/11

F# は UTF-8 推奨だった

どうやら、F#は UTF-8 推奨みたい ソースファイルの文字コードを UTF-8 にしてコンパイルすると、Shift-jis では文字化けしていた文字列が普通に表示される。
○ let str = "表示する"
だけど、ソースファイル内での以下の表現は正しく処理されない
× let strb = "表示する"B   // この時点で正常なバイトデータが得られない
× 'あ'   // syntax error
とはいえ、次の表現は正しく処理される
○ let utf_strb = Encoding.UTF8.GetBytes(str)     // 正常なUTF-8のバイトデータが得られる
○ printf "%c" str.[1]   // 「示」が表示される
F# 内部では System.Char を使っているようなので、Unicode系は得意中の得意 そのため、上の printf ではちゃんと表示されるものと思われる(実データは3バイトもあるからね) 正しく処理されない表現は、F# のソースから System.Char に渡すまでのどこかで拒否られているっぽい 直せるものなら直してほしいけど、ダメならダメで特に困ることはないかも?w ささ、ソースファイルは UTF-8 で保存してコンパイルしよう! VS2008 の場合は、標準が Shift-jis なので注意ダ  

Labels:

2008/03/05

F# はまだ多言語対応じゃなかった

F# はまだ多言語対応じゃなかった…泣ける 日本語の文字列を表示させると、文字が化け化け…うあーん… もうそろそろ多言語対応にしてもよくない? いあ、そろそろしないとやばくない? せめてUTF-8ぐらいを標準にしてほしいよー! ----------------------- .NETのクラスを使ってファイルから読み込んで表示する分には正常 ソースファイルに直接書いたものは化ける(はて? F#標準の文字コードがASCII設定とか?) ----------------------- 正常にSHIFT-JISの文字を表示できた!! けれど、わざわざ文字コードを指定してやらないとダメらしい(当たり前?) ・SHIFT-JISの文字列を bytestring という値、つまり byte [] と定義する ・Encoding.Default.GetString(???) で string にして表示
    let strb = "表示する"B
    let shiftjis = Encoding.Default.GetString(strb)
    printf "%s" shiftjis
マニュアルによると「bytestring := stringB」らしい。確かにその通りでした(^-^ こうするものだと言われるとそうなのかもしれないけど、使う側からすればこの程度は言語側で吸収してほしい おそらく現在のF#では ・string の値が与えられる (ソース上で)   ・Encoding.Default.GetBytes(string) にて byte [] へ変換     ・Encoding.Default.GetString(byte []) にて Default文字コードの string へ変換       ・変換結果を文字列として扱う という感じになっているような気がする。(どこかの時点でね) ここで問題なのが、Encoding.Default.GetBytes() なぜか、これを通すと正常なバイトデータが歪められる(^^;; 結果として文字化けのように表示されてしまう 試すとわかりますが、 "文字列を用意してそれを表示した場合" と "文字列にGetBytes()を使用した場合" の結果は同じになります。 結局現在のところ、ソースに書かれた2バイト文字はそのままでは正常に表示できない。 うーん、どうなんだろ これw # OCamlで「表示する」という文字列は、工夫しないとうまく表示されないそうです

F# wiki

wiki wiki

OCamlがやってきた

英語のF#本も良いですが、日本語でみっちり書かれている兄弟本から得られることも大きいはずです。 F#はMLの派生ということになっているようです なので、同じML派生のOCamlは兄弟であり、親ではない よって、F#とOCamlは、基本的な部分は似ていても、拡張部分になると大きな違いが表れると思われます。 あぁ、関数型脳が降臨しますように!

2008/03/04

FSharp.it

ちぇきちぇき

2008/03/03

いげ太のブログ

hogehoge!

[F#] - u_1rohのカタチ

メモ的にいろいろ載っているのでグー

2008/03/01

F# 入門 : .NET Framework で関数型プログラミング手法を使用する

丁寧に説明されているので、さらっと入れます 最初に 「#light 」 と記述するのをお忘れなく