1 名前:デフォルトの名無しさん mailto:sage [2007/08/02(木) 14:03:05 ] MSResearchから出てきた.NETで使える関数型言語のひとつF# OCAMLの流れを汲むこの言語、いろいろと面白そうなことができそう。 まだまだ英語の情報しかないこの言語について、幅広く語れ。 research.microsoft.com/fsharp/fsharp.aspx
429 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 02:00:06 ] ご回答ありがとうございます。 おっしゃるとおり、自分でもたぶん型と関数の違いがあまりわかってないと思います^^; 上の質問をした経緯です 最終的にやりたいことは、let recを用いずにYコンビネータを書きたい しかし、F#では、次のような呼び出しは型情報が∞ループして決定できない let fact self n = if n=1 then 1 else n * ((self self) (n-1)) in fact fact 10;; そこで、まずは、再帰的なデータ型を定義して用い、上記のような呼び出しを通るようにしたい (再帰的に'aを'a->'bに置き換えるような型) しかし、再帰的なデータ型とか、あまりプログラミング経験がないので 型情報を扱うプログラムからまず取り組むことにしたが、つまづいた、とう状況です 上のプログラムですが、次のようにするとコンパイルは通ります。 let apply1 f:FUNC<int,int> = f 1;; val apply1 : (int -> FUNC<int,int>) -> FUNC<int,int> しかし、自分が求めた型は val apply1 : FUNC<int,int> -> int なのですが、なぜこうなるのかはさっぱりわかってません
430 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 08:51:24 ] MLでYコンビネータを書く話なら、↓の最後にコードが載ってる 私には内容がさっぱり理解できないので、参考になるかどうかは分からんが ttp://www.kurims.kyoto-u.ac.jp/~hassei/selfref2006.pdf
431 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 09:55:54 ] >>427 は、↓にすればコンパイルが通るぞ let apply1 = function (F f) -> f 1;;
432 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 11:15:40 ] あっと、別にfunction使う必要はなかった let apply1 (F f) = f 1;;
433 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 13:03:49 ] >>430 ,431 ありがとう。とても参考になりました。 let recは言語組み込みのYコンビネータみたいなもんらしいですね 無事できあがったYコンビネータ type X = Psi_inv of (X -> (int -> int));; let psi (Psi_inv f) = f;; let Y g = let h y = g(fun x -> (((psi y) y) x)) in h(Psi_inv(h));; (Y (fun f x -> if x=0 then 1 else x * f(x - 1))) 10;; しかし、単純にF#に翻訳しただけなので 理解したとは言い難い・・
434 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 18:21:09 ] この流れなら書ける type fix<'a, 'b> = Fix of (fix<'a, 'b> -> ('a -> 'b)) let y f = (fun (Fix g as h) x -> f (g h) x) (Fix (fun (Fix g as h) x -> f (g h) x)) y (fun f x -> if x = 1 then 1 else x * f (x-1)) 5 // val it : int = 120 [1..10] |> List.map (y (fun f x -> if x <= 2 then 1 else f (x-1) + f (x-2))) // val it : int list = [1; 1; 2; 3; 5; 8; 13; 21; 34; 55]
435 名前:デフォルトの名無しさん mailto:sage [2009/02/08(日) 20:43:02 ] 同じ結論にたどり着いた type Rec<'a,'b> = R of (Rec<'a,'b> -> ('a -> 'b));; //version1 let y f = let ymaker (R proc) = f(fun arg -> (proc (R proc)) arg) in ymaker (R ymaker);; //version1 extract let y f = (fun (R proc) -> f(fun arg -> (proc (R proc)) arg)) (R (fun (R proc) -> f(fun arg -> (proc (R proc)) arg)) );; //version 2 let R_inv (R f) = f;; let y f = let ymaker proc = f(fun arg -> (((R_inv proc) proc) arg)) in ymaker (R ymaker);; //version 2 extract let y f = (fun proc -> f(fun arg -> (((R_inv proc) proc) arg))) (R (fun proc -> f(fun arg -> (((R_inv proc) proc) arg))) );;
436 名前:デフォルトの名無しさん mailto:sage [2009/02/10(火) 07:30:35 ] Programming F#: Rough Cuts Version By Chris Smith Rough Cuts Release: February 2009 Print Book Release: October 2009 Pages: 504 俺、この本が出たらF#はじめるんだ・・・
437 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 02:31:18 ] のーみそが関数型に染まってくると 「左辺値」「右辺値」という言葉に 妙な違和感を覚えだす そもそもそんな観念がないというか あえて言うなら左辺に値などない てなことを妄想してみたけどどうよ?
438 名前:デフォルトの名無しさん [2009/02/11(水) 04:31:13 ] >>437 概念じゃねーの?
439 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 08:56:56 ] >>434-435 lazyに考えれば、もっとシンプルに書けるんじゃね(´・ω・`)? let rec fix (f : Lazy<_>) = f.Force() (lazy fix f) let fact = fix <| lazy fun f x -> if x = 0 then 1 else x * f.Force() (x - 1) do fact 5 |> printfn "%d"
440 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 09:01:08 ] >>437 「let x = 1」 これは等式とは思わない方が自然じゃないだろうか。 もともとは数学の論文とかでよく出てくる 「Let x := 1.(xを1と置く。)」とかいう表記を構文にしただけなんじゃないかと想像する。 等式じゃないなら、左辺、右辺とかいう観念はない。
441 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 09:18:39 ] おまえら頭いい サイコーだ
442 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 12:21:03 ] >>439 >>429 をよく見ろ > 最終的にやりたいことは、let recを用いずにYコンビネータを書きたい
443 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 12:55:37 ] ついでに、let rec 使用可なら lazy を使う必要すらない let rec fix f x = f (fix f) x let fact = fix <| fun f x -> if x = 0 then 1 else x * f (x - 1)
444 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 13:39:14 ] >>443 > let rec fix f x = f (fix f) x あー、そっか。x つければ落ちないんだ。(´・ω・`) let rec fix f = f (fix f) と書いて、StackOverflowになってたのでlazyにしてた。
445 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 13:47:41 ] x はラムダ的に冗長に見えるけど、型推論の重要な手がかりになってるということか。 > let rec fix f = f (fix f);; val fix : ('a -> 'a) -> 'a > let rec fix f x = f (fix f) x;; val fix : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b
446 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 14:01:31 ] そのあたりのことってProgramming in OCamlに書いてある 正格評価がどうのこうので。 試してないが、確かこれでもいけたはず let rec y f = f (fun x -> y f x);; fun arg -> (proc (R proc)) argの箇所を (proc (R proc))としないのも同じ理由だと思う とりあえずfunで包めばOK,みたいな
447 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 14:31:19 ] 結局、再帰型を使うようにしたら、結論はほとんど同じだった。(´・ω・`) type Fix<'a, 'b> = Fix of (Fix<'a, 'b> -> 'a -> 'b) let run_fix (Fix f) = f let ycomb f = let g proc = f (fun arg -> run_fix proc proc arg) in g (Fix g) let fact = ycomb <| fun f n -> if n = 0 then 1 else n * f (n - 1)
448 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 14:42:02 ] >>438 正直、「観念」と「概念」の違いがわからんで調べてきた どちらも「モノコトに対する意識・考え」だが… * 観念 英語でいう idea の意味に近い オレオレ解釈的(主観的) 故に観念は多様である * 概念 英語でいう concept の意味に近い ふつうはみんなそう解釈するよねー的(客観的) 故に概念は一様である という違いがあるようだ。 左辺値、右辺値という考え方は、一般に共通の理解を得ている もの(通念)であり、それらは「概念」と呼ぶのが相応しい ということかな?
449 名前:デフォルトの名無しさん mailto:sage [2009/02/11(水) 14:45:18 ] >>448 まあニュアンスが伝わればいいんじゃね?
450 名前:デフォルトの名無しさん mailto:sage [2009/02/12(木) 07:21:21 ] >>445 冗長なんじゃなくて、正格評価の世界では意味が全く別のものになる。 let rec fix = fun f -> f (fix f) let rec fix = fun f -> fun x -> f (fix f) x 後者では x が遅延の役割をしてくれる。 Haskellのような遅延評価の世界では、確かに冗長なだけ。
451 名前:デフォルトの名無しさん mailto:sage [2009/02/12(木) 07:31:11 ] f そのものを遅延化してしまう(>>439 )のと、 引数 x を追加して遅延の役割をしてもらう(>>443 )のと、 どちらがコードの見た目的にやさしいかは明らか。w
452 名前:デフォルトの名無しさん mailto:sage [2009/02/13(金) 07:47:47 ] f (fix f) と fun x -> f (fix f) x って同義じゃないの? んー、マジで分からん
453 名前:デフォルトの名無しさん mailto:sage [2009/02/13(金) 19:50:03 ] let rec fix f = f (fix f) だと、f が渡された途端、 f (fix f) ↓ f (f (fix f)) ↓ f (f (f (fix f))) ↓ f (f (f (f (fix f)))) ↓ f (f (f (f (f (fix f))))) ↓ あぼーん 関数を返そうとはするが、fix を展開しようとして無限ループ。 let rec fix f = fun x -> f (fix f) x だと、f が渡されても、 fun x -> f (fix f) x x が渡されるまで fix は展開されない。
454 名前:デフォルトの名無しさん mailto:sage [2009/02/13(金) 19:54:11 ] ちょっと言葉足らずなので修正。 × 関数を返そうとはするが、fix を展開しようとして無限ループ。 ○ 関数を返そうとはするが、先に fix を展開してしまい無限ループ。 × x が渡されるまで fix は展開されない。 ○ 先に関数を返し、x が渡されるまで fix は展開されない。
455 名前:デフォルトの名無しさん mailto:sage [2009/02/14(土) 17:13:10 ] 関数は first-class object ではあっても 関数 = 値 ではない、と ――ここで正格評価において let rec fix f = f (fix f) なる定義で fix g を評価しようとしたら? 必死こいて値を算出しようとしてしまうんだな で、その結果、>>453 が示すように無限ループに陥る let rec fix f x = f (fix f) x なる定義で fix g を評価しようとしたら? これは部分適用だから関数オブジェクトの生成を行うのだな で、後々、(fix g) y とされたときに値の算出が始まる
456 名前:デフォルトの名無しさん mailto:sage [2009/02/15(日) 23:01:31 ] 高尚な議論の最中で流れぶった切ってゴメン 入れ子になった型宣言(ネストされた type)って無理? type a () = type b = {x : int; y : int;} ... とかすると、2つ目の type で Unexpected keyword 'type' in type definition と怒られる
457 名前:デフォルトの名無しさん mailto:sage [2009/02/17(火) 20:14:16 ] >>456 できなさげ 確かに C# ではインナー クラスできるけど Java と違ってそんなに多用されるもんでもないような てか例示のコードならタプルでいいんじゃ?
458 名前:デフォルトの名無しさん mailto:sage [2009/02/17(火) 22:01:21 ] ありがと、やっぱ出来なさそうですね。 まぁ、確かにタプルでも機能するんですが、 各要素へのアクセスが面倒なんで レコードの方が扱いやすいなぁと。
459 名前:デフォルトの名無しさん mailto:sage [2009/02/18(水) 01:02:15 ] .NET 言語なんで C# 基準で考えてしまいがちだが F# は OCaml ベースなんだぜ? internal すらぬるい、どうしても外部から隠蔽したいというなら シグネチャ(.fsi)ファイルを書けばいいじゃないか と、眠たいので調べもせずにいってみるテスト
460 名前:デフォルトの名無しさん mailto:sage [2009/02/18(水) 12:53:16 ] >>259 公開するものだけをシグネチャ ファイルにしたら上手くいった。 なるほど、fsi はこうやって使うのか。 改めて読み直してみたら本には書かれていたけど、 いままで自分には無関係だと思って無視してた。 もうちょっと調べてみる。 じつは OCaml は見たことも触ったこともないんだけど、 やっぱ一通り触れてみた方がいいのかな・・・
461 名前:デフォルトの名無しさん mailto:sage [2009/02/18(水) 20:18:22 ] >>259 言い忘れてた ありがと
462 名前:デフォルトの名無しさん mailto:age [2009/03/04(水) 22:31:36 ] seq<int> 型に拡張メソッドを加えたいです。 パラメータを int 型に制約しなければ例えば次のように出来ました。 type System.Collections.Generic.IEnumerable with member this.H = Seq.hd this これを seq<int> 型の時のみ拡張することは出来ないのでしょうか。
463 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 03:49:18 ] これってVisual Studioから使えるの?
464 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 04:09:35 ] つかえるよ。 男は度胸。ものは試し。 まずはインストールしてミソ。
465 名前:デフォルトの名無しさん [2009/03/07(土) 09:32:33 ] 2008のProでしか駄目でした的な感じなのだが・・・orz 2008 Pro安く売ってないのかね
466 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 13:05:24 ] エディション比較ちゃんと見れと www.microsoft.com/japan/msdn/vstudio/products/vs08/compare.aspx 相変わらず Visual Studio 2008 Shell は知られてないなと msdn.microsoft.com/ja-jp/vsx2008/products/bb933751.aspx アドインなんだから devenv.exe のあるなしで判断できるだろうと
467 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 17:19:53 ] 使ってる人もっとなんか書いてくれ Scala がどうとか言ってる同僚を黙らせたい …俺? 日本語の本が出てからやるわw
468 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 23:49:03 ] F# のことを勉強しようかと思ったが、至るところ null があるって聞いた時点で、萎えた。
469 名前:デフォルトの名無しさん mailto:sage [2009/03/07(土) 23:56:45 ] 何を言ってるんだ?おまえは?
470 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 00:07:37 ] >>467 どうとか言ってる内容にもよるわけだが、黙らせる方法ってのは。 関数型サイコーとでも言っているのかい?その同僚は。
471 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 02:04:51 ] nullがあるって変な表現だよね。
472 名前:デフォルトの名無しさん mailto:sage [2009/03/08(日) 15:24:28 ] >>466 kwsk 2008 StdあればF#の拡張機能は組み込めるってこと? あと、VS2008 の Shell 版なら本体買う必要なすってことなのかな?
473 名前:472 mailto:sage [2009/03/08(日) 15:31:46 ] ごめん、検索したら一杯情報出てきた。 大体あってた。 いげ太のブログ: Microsoft Visual Studio 2008 Shell (integrated mode) で F# 無償開発環境 igeta.cocolog-nifty.com/blog/2008/04/vsshell.html > Microsoft Visual Studio 2008 Shell (integrated mode) を導入すれば、 > 無償の F# 開発環境が手に入る。噛み砕いて言えば、C# も VB.NET も C++/CLI も、 > 何の言語もバンドルされていない Visual Studio 2008 が、タダで手に入るってことだ。 > そして、VSShell がインストールされた状態で、F# をインストールすればよい。 > そうすれば VSShell に F# が組み込まれるのだ。 Visual Studio で F#の開発を行う - ピコピコの日記 d.hatena.ne.jp/net-k/20080911/1221099444 > F#はVisual Studio 2008 もしくは、Visual Studio 2008 Shellから利用することができる。 > Visual Studio 2008 を持っていないので、無償で公開されているVisual Studio 2008 Shellをダウンロードした。 > ちなみに、Visual Studio 2008 Shell とは、C++やC#などの開発環境が何も入っていない状態のVisual Studio 2008で、 > Visual Studio向けの開発環境をSDKを使って組み込むことができる。 Visual Studio Shellダウンロードしてくるわ。 ありがとう。
474 名前:デフォルトの名無しさん mailto:sage [2009/03/09(月) 22:36:42 ] >>468 はこれか。 d.hatena.ne.jp/camlspotter/ いろいろ挑発的なことが書いてあるな
475 名前:デフォルトの名無しさん [2009/03/22(日) 17:40:50 ] 下がりすぎだろ
476 名前:デフォルトの名無しさん [2009/03/24(火) 16:39:37 ] FParsecの話なんかやってくれないかなあ
477 名前:デフォルトの名無しさん mailto:sage [2009/03/24(火) 20:11:44 ] こやつめw