オリジナリティあふれるタイトルでLTしてきた

1月15日にCLR/Hの第54回勉強会が開催されました。
そこでLTをさせていただきました。何気に人生初LT。
初のLTがこんなにオリジナリティあふれるタイトルでいいのか悩みましたが、ダダすべりでむしろ心地良かったほどです。
資料を公開したいのですが大人の事情で難しいので、内容を簡単に紹介したいと思います。

続きを読む

めもりんこ

ゼクルッシュさん*1が「メモ化」について面白い記事を書かれていました。
メモ〜化したりスマス。 Memoization and Tail Recursive Function - Bug Catharsis


ぼくならこう書く!というのを少し考えてみました。
最初はコメント欄に投稿しようかと思ったのですが、はてなのコメント欄は半角スペースが削除されちゃうので・・・。

open System
open System.Collections.Generic 

let create<'Key, 'Value when 'Key : equality> () = Dictionary<'Key, 'Value> ()

let memoize f =
    let dic = create ()
    fun x ->
        if not (dic.ContainsKey(x)) then dic.Add(x, f x)
        dic.[x]

let curry2 f x y   = f (x, y)
let curry3 f x y z = f (x, y, z)
let uncurry2 f (x, y)    = f x y
let uncurry3 f (x, y, z) = f x y z

let memo curry uncurry f = let m = memoize (uncurry f) in curry m
let memoize0 f = let m = lazy f () in (fun () -> m.Value) //201115日 修正
let memoize2 f = memo curry2 uncurry2 f
let memoize3 f = memo curry3 uncurry3 f

人間それぞれ個性を持っていますから、人と人とを比較することはできませんし、そんなことに意味はありません。
でもF#のタプルは比較することができます!
(1, 2) = (1, 2) は true です。
というわけで Dictionary のような表現も可能となります(when 'Key : equality を満たす)。
そのトリックを使ったのが上記のコード。
memoize0はちょっと卑怯ですが、卑怯なくらいが丁度いい。(え?)←改良しました!


一応実行例も載せておきます。(対話環境):

> let f0 () = printfn "I'm f0 !" ; 0 ;;
val f0 : unit -> int

> let f0' = memoize0 f0 ;;
val f0' : (unit -> int)

> f0' (), f0' ();;
I'm f0 !
val it : int * int = (0, 0)


> let f1 x = printfn "I'm f1 !" ; x + 1 ;;
val f1 : int -> int

> let f1' = memoize f1 ;;
val f1' : (int -> int)

> f1' 9, f1' 9 ;;
I'm f1 !
val it : int * int = (10, 10)


> let f2 x y = printfn "I'm f2 !" ; x + y ;;
val f2 : int -> int -> int

> let f2' = memoize2 f2 ;;
val f2' : (int -> int -> int)

> f2' 2 8, f2' 2 8 ;;
I'm f2 !
val it : int * int = (10, 10)


> let f3 x y z = printfn "I'm f3 !" ; x + y + z ;;
val f3 : int -> int -> int -> int

> let f3' = memoize3 f3 ;;
val f3' : (int -> int -> int -> int)

> f3' 2 3 5, f3' 2 3 5 ;;
I'm f3 !
val it : int * int = (10, 10)

> f3' 3 2 5 ;; //順番を変えると・・・
I'm f3 !
val it : int = 10

ScalaとHaskellがF#に救いの手を

F# Advent Calendar jp 2010 第1回目!


F#の弱点(?)のひとつに、C#でいう try-catch-finally の仕組みが無いという点が挙げられます。
F#ではどのようにするかというと、try-with と try-finally をネストすることによって解決します。
「この、ねすとねすとした感じ、どうにかなりませんか!」


この問題を解決するヒントが、ScalaHaskellにあります。
ご存知(?)Either型!

続きを読む

属性の定義

F#での属性の定義に関する情報って何か少なくない・・・?
気のせいでしょうか。
まあC#とほとんど変わらないのですが、一応例を残しておこうと思います。

open System

//
// サンプル属性
//
[<AttributeUsage(AttributeTargets.All)>]  // こんな属性を付けよう
type InformationAttribute(summary : string) =
    inherit System.Attribute()  // こんなクラスを継承しよう
    member self.Summary = summary

// 属性を取ってくる関数のサンプル
let info (t : Type) =
    let f (t : Reflection.MemberInfo)=
        t.GetCustomAttributes(typeof<InformationAttribute>, false)
        |> Array.map (fun x -> x :?> InformationAttribute)
        |> Array.iter (fun x -> printfn "%s : %s" t.Name x.Summary)
    f t
    Array.iter f (t.GetMembers ())
    printf "\n"


// つくった属性を付けてみます

[<Information("死んだじいちゃんが大事にしていたクラスです。")>]
type AttrTestClass(x) =
    [<Information("貧弱なフィールドです") ; DefaultValue>]
    val mutable MyVal : int
    [<Information("繊細なメソッドです。")>]
    member self.MyMethod () = ()
    [<Information("大胆なプロパティです。")>]
    member self.MyProperty = x

[<Information("紳士的なenumです")>]
type AttrTestEnum = XXX = 1 | YYY = 2 | ZZZ = 3

そして、例えば対話環境で以下のようにしゃべってみます。

> info typeof ;;
AttrTestClass : 死んだじいちゃんが大事にしていたクラスです。
MyMethod : 繊細なメソッドです。
MyProperty : 大胆なプロパティです。
MyVal : 貧弱なフィールドです

val it : unit = ()
> info typeof ;;
AttrTestEnum : 紳士的なenumです

val it : unit = ()

VS上では「///」によるXMLコメントのほうが便利だけども、対話環境で使うことを目的としたスクリプトにはこんな属性を付けてやってもいいかもしれません。
いらないですね。そうですね。わかりました。すいません。

GeneralizableValueAttribute

特に意味はないのですが、頭痛を癒すためにVisual Studioを立ち上げました。ただのひとり遊びです。

type Person() = class end
type Dog()    = class end
type Cat()    = class end

type MyCollection<'T>() =
    static let arr = new ResizeArray<'T>() // static がミソだよ!
    member self.Add = arr.Add
    override self.ToString() = typeof<'T>.Name + "\t× " + arr.Count.ToString()

[<GeneralizableValue>]
let collection<'T> = new MyCollection<'T>()

[<EntryPoint>]
let Main args =
    collection.Add <| Person()
    collection.Add <| Dog()
    collection.Add <| Cat()
    collection.Add <| Dog()
    collection.Add <| Cat()
    collection.Add <| Cat()
    
    printfn "%A" (collection<Person>)
    printfn "%A" (collection<Dog>)
    printfn "%A" (collection<Cat>)
    
    0

Person  × 1
Dog × 2
Cat × 3
続行するには何かキーを押してください . . .
Main関数内だけ見るとなかなか不思議。
手当たり次第に詰め込んだのに、中の人がきちんと仕分けしてくれています。


ちなみに、GeneralizableValueAttribute を付けると関数に変換されるようです。
追記:コメント欄で いげ太さんにご指摘いただきましたが、この属性の有無は関係ないようです。
上の例だと以下のように展開されていました。

[GeneralizableValue]
public static MyCollection<T> collection<T>()
{
    return new MyCollection<T>();
}

Visual F# Express Edition の入手方法

あみだら

2012/10/27 追記
Visual Studio Express 2012では無償でF#が使えます!
http://d.hatena.ne.jp/Nobuhisa/20121027/p1


おそらく、「F# Express」で検索する方が多いと思うので、その人たちを釣る誘導するためのタイトルです。


喜んでください!F#は無償で利用することができます!
ただし、「Express Edition」というものは用意されていません。
以下のものをインストールしてください。


Visual Studio Shell というIDEを用意し、その中にF#を組み込む形になります。
F# CTPだけでも利用可能ですが、この場合コマンドラインで実行することになります。
マシンパワー的にVS2010は厳しい!という方は、VS2008も選択可能です。


ダウンロードは以下から:


なお、F# CTPはどんどん更新される可能性があるので、ダウンロードする前に最新版がないか確認されることをオススメします。(上記のリンクは現時点での最新版です)

SharpDevelop

SharpDevelop(http://sharpdevelop.net/OpenSource/SD/)でもF#がサポートされているようです。

MonoDevelop

MonoDevelop(http://functional-variations.net/monodevelop/)を利用すれば、Linux環境でもIDEを使ってF#を楽しめます!

その他の情報

F#プログラミングをもっと楽しくするF# PowerPackというライブラリもあります。
あわせてどうぞ。


いくつかある書籍の中で、(現時点で)もっとも良いのは以下のものです。








最近、「F#って無料で使えないのか!」という嘆きを沢山目にするので、
今更ながら検索対策ということでまとめてみました。
何気にF#の注目度が高まってきている気がする今日この頃。

プログラミングF#実践F#