関数型プログラミング言語Haskell Part10
・日本語の扱いについて
Haskell98によると、Charは一つのUnicode文字を表す(6.1.2)。
これに従って、比較的新しいHugsやGHC(6.4系を含む)ではCharは32ビット整数になっている。
ただし、どちらも入出力に際しての変換が完全でない。具体的には、
・ソースコード中の文字列リテラル
・System.IOライブラリでの入出力
が問題になる。
1. GHC6.4.2以前
ソースコード・入出力ともLatin-1を仮定する。Latin-1ではバイト値と
コードポイントが一致するので、入力時には外部エンコードの各バイトがそのままCharに
入り、出力時にはCharの下位8ビットのみが出力されるような実装になっている。
このため、あるエンコーディング(Latin-1とは限らない)の入力をgetLineで受け取り、
それをそのままputStrで表示すれば、入力時とおなじエンコードにおいて正しく表示される。
これを利用して、[Char]を、本来のコードポイントの列としてではなく、特定のエンコードの下での
バイト列として使うことができる。ただし文字列リテラルについては、GHCはLatin-1として
不正な文字を受け付けないので、EUC-JPのような例外を除くと、単純にリテラルを使うことはできない。
2. GHC6.6
ソースコードにはUTF-8、入出力にはLatin-1を仮定する。このため、EUC-JPでリテラルを直に
書くことはできない。
(続く)
(続き)
3.最近のHugs(非WindowsかつCのwchar_tがUnicodeの環境、というかLinux)
ソースコード・入出力ともロケールのエンコードを利用する。
4.最近のHugs(Windows)
ソースコード・入出力ともLatin-1を仮定する。ただし文字列リテラルにShift-JISを使ってもエラーにならない。
5.最近のHugs(それ以外)
未調査。
・結局どうするか。
規格どおりにCharにUnicodeを入れるか、Charを単なるバイトとして扱うかの二択。
i. CharをUnicodeとして扱う
(3)以外の場合入出力で変換が必要。(2)または(3)以外の場合文字列リテラルでは
明示的なエスケープ(たとえば"\22234")が必要。
ii. Charをバイトとして扱う
(3)ではファイルをバイナリモードで開くなどの対策が必要。(1)でEUC-JPを使う場合と(4)
を除き文字列リテラルでは明示的なエスケープ(たとえば"\143\153")が必要。
lengthやisAlphaのような関数、およびwin32パッケージの関数(win32API)が正しく動作しない。
//
/ / パカッ
//⌒)∩__∩
/.| .| ノ ヽ
/ | | ● ● |
/ | 彡 ( _●_) ミ まピョーん☆
/ | ヽ |∪| /_
// │ ヽノ \/
" ̄ ̄ ̄ ̄ ̄ ̄ ̄(..ノ
前スレ11 :デフォルトの名無しさん :2008/05/17(土) 20:00:31
そろそろ、テンプレの GHC 6.6 の日本語の取り扱いについて書き改めて欲しい。
1. ソース中の文字列 hello = "こんにちは" :: String は UTF-8
2. これを ghci で表示することは可能:(ただし、環境変数 LANG を UTF-8 にしておくこと、
また、ターミナルも UTF-8 で入出力できるようにしておくこと)
Main> print hello
こんにちは
Main>
3. 入出力 IO は Latin-1 だが、
package utf8-string (
http://code.haskell.org/utf8-string/)
を導入することにより、入出力を UTF-8 にすることができる
4. その他の文字列エンコード(ShiftJIS, JIS, EUC-JP など) は、
package iconv (
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/iconv)
で UTF-8 な文字列にする
とまあ、こういうことで、日本語表示できるわけだ。iconv package は MacOSX と *BSD では
cabal を少しいじらなければいけないことに注意しろよ(iconv.cabal のコメントに書いてある)
よろしくたのむ、な。
テンプレここまで。
関連書籍に二冊追加。
Unicodeの入出力について、誰かまとめてくれるとうれしい。
刀、 , ヘ
/´ ̄`ヽ /: : : \_____/: : : : ヽ、
,. -‐┴─‐- <^ヽ、: : : : : : : : : : : : : : : : : : : : : : }
/: : : : : : : : : : : : : :`.ヽl____: : : : : : : : : : : : : : : : : : /
,. -──「`: : : : : : : : : :ヽ: : : : : : : : :\ `ヽ ̄ ̄ ̄ フ: : : : :/
/: :.,.-ァ: : : |: : : : : : : : : :\: : : : :: : : :ヽ \ /: : : :/
 ̄ ̄/: : : : ヽ: : : . . . . . . . . . . .、 \=--: : : :.i / /: : : : :/
/: : ∧: \: : : : : : : : : : ヽ: :\: : : 〃}/ /: : : : :/ 、
. /: : / . : : :! ヽ: : l\_\/: : : : :\: ヽ彡: : | /: : : : :/ |\
/: : ィ: : : : :.i: : | \!___/ ヽ:: : : : : : :\|:.:.:.:/:! ,': : : : / |: : \
/ / !: : : : :.ト‐|- ヽ \: : : : : l::::__:' :/ i: : : : :{ |: : : :.ヽ
l/ |: : :!: : .l: :| \: : : l´r. Y {: : : : :丶_______.ノ: : : : : :}
l: : :l: : :ト、| 、___,ィ ヽ: :| ゝ ノ '.: : : : : : : : : : : : : : : : : : : : : : /
|: : :ト、: |: :ヽ ___,彡 ´ ̄´ ヽl-‐' \: : : : : : : : : : : : : : : : : : イ
!: :从ヽ!ヽ.ハ=≠' , ///// ///u /  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
V ヽ| }/// r‐'⌒ヽ イ〉、
ヽ、______ー‐‐' ィ´ /:/:7rt‐---、 こ、これは
>>1乙じゃなくて
ィ幵ノ ./:/:./:.! !: : : : :!`ヽ ポニーテールなんだから
r‐'T¨「 |: | !:.∨:/:./: :| |: : : : .l: : : :\ 変な勘違いしないでよね!
/: : .|: :| !:.!ィ¨¨ヾ、:.:/ !: : : : l: : : : : :.\
今Emacs使ってHaskellやってますが、引数の型とかに合わせた候補リストみたいなの
出す機能があるエディタってありますでしょうか。
>>10 emacsでも出来た気がするけどね。
なんていうモードだったか忘れたけど。
viでもjeditでも出来るよ。
jeditはわりと惜しいエディタでもある。java製だし、プラグインのAPIは洗練されてないし、不安定だし、という理由で。
>>11 emacsのhaskell-modeは使ってますけど、型から候補を出したり補完したり
するのは知りませんでした。
viで出来るってのも初耳なんだが、どうやるの?
vim にはプラグインがあったような。詳細は覚えてないけど、ググればすぐ見つかるはず。
haskell for vim のことを言ってるのであれば
そんな高度なことは出来なかった気が
16 :
sage:2009/01/19(月) 12:26:27
初心者質問ですが、derivingというのは特定classのみ許される仕様なんでしょうか。
自分でderivableにする方法ってありますか?
19 :
17:2009/01/28(水) 22:35:28
>>18 ありがとうございます。拡張なんですねぇ。頑張って理解してみます。
Javaなどの言語をやってきたんですけど、同じ関数名で引数の型が
相違するようなのを簡単に作れないのかなぁ、と思ったのです。組み込み
のclass(Eqなど)で通常は十分、ということなんでしょうかね。
>同じ関数名で引数の型が相違するようなのを簡単に
Javaのどういうコードが念頭にあるのか分からんけど、
もし実装の継承がしたいということなら
>>18は大して訳に立たないと思う
手でインスタンス宣言を書くしかないんじゃないか
単にオーバーロードのことを言ってるように思えるのだが
どっちにしてもderiving関係なくね
22 :
17:2009/01/29(木) 20:03:34
すみません、ちょっと曖昧でした。オーバーロードではなくて、
多相な関数を定義する簡易的な方法についての質問です。
>>18というのは、Lispのマクロ的なものなんでしょうか。
本当にderivingが使える型クラスを作りたいなら
>>18でいい(ただしできることは限られる)んだけど、
>>19や「多相な関数を定義する簡易的な方法」を聞くと違うような気がする
(Javaにはderivingに相当する機能はないよな?)
なにか具体例を見せてくれれば分かると思うが
derivingの意味を誤解してるかもしれないので念のためまとめると、
・Haskellの型クラスはインタフェースを表現する(Javaのinterfaceみたいに)
・ある型クラスの規定するインタフェースについて、個々の型における具体的な実装を書くのがインスタンス宣言
・定型的なインスタンス宣言を自動生成する機構がderiving
>>18のは、自分で定義したクラスに対してこの自動生成を可能にする方法の一つ
構文的にはderivingというキーワードを使わないけど、やってることは同じ
存在型(forall)のことかな?
>>22 多相な関数って、例えばこんな関数?
id :: * -> *
id x = x
26 :
17:2009/01/30(金) 11:24:58
>>23 ありがとうございます。どうもJavaのイメージとごっちゃになってる
部分があって、勘違いしてるような気がしてきましたw
型ごとに振る舞いが違う関数であれば、個別にinstanceしなければ
ならないでしょうし、そうでなければ
>>25のような形になるわけですね。
27 :
17:2009/01/31(土) 12:06:49
もう一つclass関連での疑問なのですが、そもそも、オーバーロードが必要な場合
には逐一class宣言とinstance宣言が必要だ、というのは何か必然性があるんで
しょうか。class書いてもいいけど、書かなくても裏で同様のつじつま合わせをして
くれてもいいように思えるのですが。
>>27 つじつまあわせなんてしたら型推論なんてできなくなる。
型推論は、関数のこの引数はこの型じゃなければならないから・・・
みたいなことを繰り返して型を確定していくのに、
すべての関数がオーバーロードされているかもしれないんじゃ、
型を確定させることができない。
そもそもJavaなどで簡単にオーバーロードができるのは、
引数として渡される値の型が簡単に分かるから。
引数として渡される値の型と、オーバーロードされている関数の型を比較すれば
実際に呼び出すべき関数が簡単に分かる。
しかし、型推論のある言語では、型が簡単には分からないので、
class,instance宣言必須という制限をつけて範囲を限定している。
Java的な意味でオーバーロードがしたい場合は単に違う関数名を付けるのが普通
Haskellの型クラスは実行時多態を行うためにある
用語がややこしいけど、
Haskellでいうオーバーロード(クラスを使う) <=> Javaでいうポリモーフィズム
Javaのオーバーロードに対応する機能はない
30 :
17:2009/01/31(土) 14:37:11
>>28 > つじつまあわせなんてしたら型推論なんてできなくなる。
ああ、そうでした。型推論の問題なんですね。納得です。
>>29 > Java的な意味でオーバーロードがしたい場合は単に違う関数名を付けるのが普通
やはりそうなんですね。自分はコード書く際に名前付けるのが一番悩んでしまう
ので、その辺がスッキリならんのかなぁと思ったのですが。そこは仕方ないんですね。
どうもありがとうございました。
utf8-string てのが前からあったでしょ?なんか変わったの?
普通のStringを普通にputStrして普通に文字が出る
外部コードもUTF-8固定じゃなくて選べるし、デフォルトでロケールに合わせてくれる
各種schemeインタプリタのようなaproposはghciにもありますか?
これがあるとシンボルの入力補完のシステムとかが楽に組めて便利なんですが
ghciのUIにはないと思う
ghciに補完機能がある以上内部では持ってるはずだから、
やりたいことによってはGHC APIが役に立つかも
36 :
デフォルトの名無しさん:2009/02/09(月) 20:19:27
ちょっと前に2chで関数型ユーザーを叩いてみたのだけど、
やっぱり関数型の内実は80%ほどが幻想だな、という感想を持った。
Lisp,Schemeのユーザーはすぐ折れたがHaskellのユーザーは頑固だった。
まあ純粋で美しいから信者になってしまったのだろうけど、
純粋な美しさでHaskellに勝てるものはいないだろうと思う。
しかし自然言語を目指さず数学的な記述を目指したところでいいプログラムは書けない。
数学は定理を証明するための言語で、プログラミングは定理の証明ではない。
証明出来るならプログラムなんか書く必要ないしな。
curry howard correspondence
あぁ、あとこのスレは過疎もいいところだから関数型言語叩くならhaskell-cafeにおいで
このスレは過疎な訳じゃなくて話題がないだけだろ
見てる奴は多いだろうからいいネタがあれば盛り上がると思うぜ
そういやCleanって最近話題聞かないな
>>36 Haskellユーザーとは痛み分けだったろ。それにSchemeのほうも一年以上
かかってたじゃねぇか。
Haskellの強みを論理的に教えてください。
あなたにとっての「強い」を論理的に説明してください
>>43 あなたはもう発言しなくてよろしい
次の方どうぞ
難しい話じゃなし、疑問があるなら勉強すればいいんだよ
絡みたいだけの奴はやっぱスレに張り付いてんだなあ
>>48 言わせてもらいますが、
Haskellの強みをはっきり書いた論文も書籍もありませんよ。
関数型言語はなぜあなたのコンプレックスを刺激するのか論理的に説明してください
モナドのすべてにでてくる各種モナドがイミフだったから
あれらの定義を仕様を表す論理式から導き出せるようになりたい
使ってるうちに解るとは到底思えないぐらいイミフ
IOモナドが意味不明だったので、Lispも糞だと結論付けました
攻撃的な発言は発言した内容が自分自身にそのまま当てはまると内心で思っている証拠だということに最近気づいたところなんだよ。
だから相手を攻撃するということは自分自身の弱さを曝け出すことにもなるんだよ。
こういう話題になると
今までみんなどこに居たんだと思うぐらいレスが付くなあ
>>45 全然話の流れと関係ないとこで気になったんだが
チューリング完全なら全部一緒という論調ってどこか違和感がある
CのプリプロセッサとCはどちらもチューリング完全性だと思うが
単純に構文糖衣という意味以上に、能力的にはCのほうが高いと思う。
スケーラビリティの点で。
Cで関数引数nに、簡単に大きな引数を指定出来るのに対し
プリプロセッサで同じことをやろうとすると、
大きな引数nの値と同じ数だけ自分でデータを作る必要が
あったように思う
そういう意味でプログラム自身をデータと見なせるLispは
かなりスケーラビリティ的な意味で能力が高いと思うわ
しかし、プログラム自身をデータと見なせるだけでは
まだスケーラブルにならない世界もあるんじゃ無かろうか
うまく説明できんが、
自然数→整数→実数→複素数の進歩のように
>>36 Haskellユーザーよりも、Lisp,Schemeの方が、バカの扱いに慣れているって事が分かりました。
自然言語を目指すとか10年古い釣りワードが入ってるし
10年どころか、30年古いぞw
>>61 この子大学生かな。
知らないことも多そうだし、覚えたての言葉を使いたくて仕方が無いようにみえる。
もう少し論文とか読めばどんな研究している人がいるのかもわかってくるだろうし、
今からあんまり頭固くしてほしくないなぁ。
2chで煽って騒いだってしょうがねーだろ。
本気で相手してくれるやつなんていないのわからないのかなぁ。
ここのやつらも本気で相手にしてるのは論文の方だと思うし、2chは遊びと割り切ってるはず。
関数型言語が今後どういう風に発展していくのかという展望がまだ掴めていないなら、
まずは論文をたくさん読めば良いと思うよ。
言いたいことがあるなら論文で書いてくれ。
とマジレス
論文読むより実用的アプリを書くほうが実際ためになると思うが。
>>64 もちろん手を動かしてプログラミングしてみないとわからないこともある。
論文を読むのは、自分が気づかなかった別の価値観を発見することでもあり、
ほかの人がどういうことに興味を持っていて
どうすればその人たちの助けになるのか知るためでもあるんだよ。
こういうことを書くとブログや掲示板でも良いじゃないか、と思うかもしれないが、
ブログや掲示板は雑音に埋もれてしまうのが常だから、
言いたいことがあるなら是非とも論文で書いてくれ。
>>61 多分LINQあたりで「やべ、C#って最強言語じゃね?」ってなって、一気に信者化したんだろうな。
かわいいねぇ。
馬鹿の壁
自分は一般プログラマなんですけど、実際のところ研究者たちの実験的ツール
としてのHaskell、ではなくて実用アプリへの具体的な一歩を目指そう、という
動きはありますか?
例えば、RubyはRailsで目立ったわけですけど、似たようなキラーフレームワーク
のようなものが開発中とか、企業で予算をつけてやってるとか、そういう動きはあるん
でしょうか。
Haskellの本を色々見てると実に楽しいんですが、やっぱりHaskellerの大半は
研究として興味あるのであって、実用アプリについてはあまり興味ないのかな
とも感じます。
そんなあなたにRealWorldHaskell
>>69 > 自分は一般プログラマなんですけど、実際のところ研究者たちの実験的ツール
> としてのHaskell、ではなくて実用アプリへの具体的な一歩を目指そう、という
> 動きはありますか?
それが研究なんだけどw
72 :
デフォルトの名無しさん:2009/02/11(水) 12:04:09
73 :
69:2009/02/11(水) 12:28:31
>>70 そうなんですけど、あれは一般に広まってるアプリの実装例の解説書ですよね。
やっぱり、JavaやRubyにあるようなFrameworkと等価なもの、且つ関数型の
魅力が発揮できてるものが無いと火がつかないんじゃないかなぁ。
C#なんかは、自分は好きじゃないですけど、そういう利便性の追求という点
ではそれなりによく出来てるとは思います。皆が欲しがりそうなものをよく
揃えてるなぁと。
Haskellerはそういうのは興味なくて、もっと言語自体の面白さを追求する
ことが多いんじゃないでしょうか?
>>73 JavaやRubyで使われているフレームワークと等価なものがほしいなら
JavaやRubyではどうしてダメでHaskellなのか
というのが論文では必要になりますね。
それが言えなければHaskellで実装する必要も無いでしょう。
>>73 > Haskellerはそういうのは興味なくて、もっと言語自体の面白さを追求する
> ことが多いんじゃないでしょうか?
というよりもむしろ純粋関数型言語で実用的でコミュニティも活発なのがHaskellぐらいしかないので、
関数型言語でもっとも効率的にプログラミングするにはどうすればいいか、
というのを研究する材料に使われることが多いというだけですね。
既存技術を持ち込むことにはあまり興味がないというのは正しい見方かもしれないけれど。
既存技術を持ち込むのに適した関数型言語ならOcamlとかのほうが適任かもしれないね。
むしろ、そういう考え方をHaskellに持ち込まないでほしいというのが俺の思いでもあるし、
多くのHaskellerもそう思っているはず。
既存技術っていうのはオブジェクト指向で培った技術という意味ね。
既存技術って言ったらいろいろ含まれすぎだから。。
77 :
69:2009/02/11(水) 12:59:24
もちろん、オブジェクト指向とか持ち込む必要ないですよ。等価という言葉に
語弊があったかな。
そうではなくて、こうすりゃ簡単にWebアプリができちゃいますよ、みたいな
ものが必要じゃないのかなと。だけど、Haskeller一般はそんな量的な問題
関心なくて、もっと質的なことを追求したい、という感じがするわけです。
Railsのように実装手順が簡易且つ明確で、しかも副作用の無いことから
くる不具合の低減、並列処理の親和性なんかをアピールした、お手軽
フレームワーク、ライブラリが出てくるとぐっと違ってくると思うわけです。
要するに、Haskellが世間でお金になる。そういう状況ってこないのかなぁと。
>>77 オブジェクト指向に親和性が高い技術ってあるでしょ?
そういうのはそのまま持ち込めない、あるいは持ち込んでも不細工。
例えばオブジェクト指向で人気が高いデザインパターンとかはそのまま関数型言語に持ち込んでも不細工だし、
Railsにしたってオブジェクト指向を基盤としているからそのまま関数型言語で使うと不細工。
関数型言語で似たような機能をどのように違和感無く実現するか、っていうのは一つの研究テーマになってるよ。
まだ研究が実っていない部分が多いから、こうすればいいのになんでやらないんだ、っていう外部の感想は良く聞くけどね。
OCamlは一応オブジェクト指向機能がついているからオブジェクト指向の技術がそのまま持ち込めるんだよ。
だから関数型言語の中ではわりと人気が高いのかな。
80 :
69:2009/02/11(水) 13:17:50
>>78 いや、ちょっと分からないです。Javaなどで使われてる実装パターンがHaskellにも
応用なんかする必要ないと思いますよ。
自分が言ってるのは、RailsをHaskellに移植しろ、って話じゃないんですよね。そうじゃ
なくて、Haskellならではの、だけど利便性ではRailsに負けないライブラリが欲しいなぁ
ということなのです。
Haskellが広まってそれが普通の開発でお金が取れるようにならないかな?っていう
素朴な願望なんですね。
不細工だろうが何だろうがとりあえず動くなら持ち込めばいいと思うけどな
それがなされてないなら需要がないんだろ
>>77 HAppS
A web framework for developers to prototype quickly, deploy painlessly, scale massively, operate reliably, and change easily.
http://happs.org/ こういうの?使ったことないけど
>>80 > Haskellならではの、だけど利便性ではRailsに負けないライブラリ
そういうのも含めて言っているよ。
研究中としかいいようがない。
文句言う前に論文あさって、やりたいことがあるなら人に言う前に自分で作ったら良いじゃん。
できたら論文にするなり、製品にするなりしたほうが自分のためになるよ。
Haskellが得意とするのは二つだ
lambda-calculus と pi-calculus
オブジェクト指向?どこの原始人ですか、あんたw
Haskellerは言語自体の信者なんであって
実用ソフト書くことになんか興味ないだろ
もともと言語自体実用的じゃないし
>>82 (1) モノをつくる、(2) 論文を書く、(3) 文句を言う、の中で
わざわざ2chで、どんなバカでもお手軽に自尊心にエサをやれる(3)を選んでるヤツに対して無茶いうなw
>>84 Haskeller全体の傾向のことは分からんが、実用に興味がある奴はそれなりに居るよ
ライブラリがそれなりに整備されていってるのが証拠
言語仕様が実用的じゃないってのは意味不明
>>84 あなたにとっての「実用的」を論理的に説明してください
>>87 実用プログラムが簡単に書けることだな
テキストエディタとか、表計算ソフトとか、お絵かきソフトとか
人の楽しみや金銭的利益を発生させる役に立つことが出来るプログラムが
簡単に書けることだ
>>88 そんなのも書けないなら一からHaskellの勉強(笑)やり直せ
そろそろ勝利宣言とかくるのかな?
Yiとか割と夢が広がるようなソフトもあるけど、
これは俺がemacs厨なだけかもしれん
>>79 OCamlはオブジェクト指向の技術があるからわりと人気が高いってそれマジで言ってんのww?
>>93 大真面目。
実際、ただのCamlだったころはほとんど人気が無かった。
オブジェクト指向でも開発できる、というのが心理的な安心感を与えるのだろう。
お前らってオブジェクト指向をやってる奴は全員バカだと思ってるの?
96 :
デフォルトの名無しさん:2009/02/11(水) 14:15:09
OCamlはF#人気に便乗してるだけだろ
もっとも、F#はオブジェクト指向は排除されたようだが
違うって。
F#はOCaml人気の後に出てきた後発組
まぁ、GUIソフトをうまく書けるのか、っていうのはそれなりに重要な点だと思う。
でも、GUIソフトの書き方で、これがすばらしい、理想的だっていう
言語、フレームワークにはまだ出会ってないので、
何が必要なのかとかはよく分からん。
GUIはいろいろ考えるよりも、実直に状態マシンで仕様化して、
それを書き下したほうが結局は分かりやすくなるような気もするし、
そういう意味では、Haskellはむしろ書きやすい言語なのかもしれない。
Yampaとか全然使い方がわがんね
>>88 3点質問します
・あなたはどの程度Haskellが使えますか?
・言語仕様とラブラリやコンポーネントの話がごっちゃになっているのは何故?
(それとも何のライブラリも使わずに0からお絵描きソフトや表計算ソフトを作るってこと?)
・BtoCだけでなくBtoBも考えたら、どの言語が一番「金銭的利益を発生させる役に立つことが出来ている」と思いますか?
xmonadのソースでも読んでみたら?
言語として副作用もまともに扱えないのにGUIもクソもないでしょう
>>95 いやそうじゃなくて、OCamlのオブジェクト指向部分はかなり悪評高いんだよ。
>>94 OCamlのオブジェクト指向はかなり人気がないことをもちろん知った上での発言だよね?
何かそれでもOCamlのOOP部分に利点があるというならそれはどんな点?
GUIの書き方はGrapefruitが個人的な理想にかなり近い
ライブラリ自体は全然実用段階ではないけど
てか
>>102=84なのか?
だったらマジで勉強しなおしたほうが良いと思うぞ。
副作用無しでイベント駆動系が綺麗に実装できたら面白いなぁとか思ってるけど
gtk2hsはIORef使いまくりで吹いたw
>>102 たぶんHaskellを誤解してるな
Haskellに副作用はないけど、副作用とは別の方法でちゃんと入出力ができるから心配要らんよ
>>103 コミュニケーションが取れないな。
お前はOCamlまたはF#の人気の根拠は何だと思っているんだ?
109 :
69:2009/02/11(水) 14:30:40
>>81 > HAppS
そういうの。だけど、Jakartaプロジェクトにあるようなレベルとはやっぱり違うんですよね。
>>82 > 文句言う前に論文あさって、やりたいことがあるなら人に言う前に自分で作ったら良いじゃん。
あはは。すみません、自分はそこまでできません。
Haskellerの皆さんって頭イイ人多いと思うんですよ。そこでうまく金にする方向へは行かない
んでしょうかね。
>>108 >F#の人気の根拠
そもそも人気ではないと思うんだが。
>OCamlの人気の根拠
型推論とかがあるからじゃないかな。
で、Haskellみたいにモナドにくるんだりせずに直接副作用操作が書ける、という手軽さ。
+
実用的なライブラリもそこそこ揃ってる。GUIツールキットとか。
>>106 Grapefruitはgtk2hsのラッパとして動くけど、そのへんをうまく隠蔽してるよ
ボタン一個を表示して、クリックされる度にボタン上のテキストの"*"が増えていくサンプル
Grapefruit付属のexampleから抜粋
mainCircuit :: (StdToolkit toolkit) => UICircuit Window toolkit era () (DSignal era ())
mainCircuit = proc () -> do
rec let
title = pure "Simple"
text = SSignal.scan "*" (const . ('*' :)) push
X :& Closure ::= closure `With` X :& Push ::= push
<- window `with` just pushButton
-< X :& Title ::= title `With` X :& Text ::= text
returnA -< closure
GUIにあんまり興味ないけど、HaskellのGUIライブラリとか親和性とかについて前に誰かまとめてくれてたね。
nobsunだっけ?
横からすまんが
>お前はOCamlまたはF#の人気の根拠は何だと思っているんだ?
OCamlやF#って人気あるの?
単なるあなたのマイブームでない「人気」の証拠を、示してもらえますでしょうか?
Radditとか見てもあまり話題にあがってないと思います。
日本ではF#発表されるまで全くの無名だろ>OCaml
日本語の本なんてここ3年にでたのしかないし。
>>114 MicrosoftがVisual StudioにF#を乗っけようとしているから。
Microsoftは合理的な資本主義の営利企業だから儲からないことはやらないだろう。
そのMicrosoftがF#を打ち出してるんだから人気がある、あるいは人気が出る、あるいは人気を出させる、
と判断したからだろう。
>>117 Visual J#って覚えてる?あとその人気についても。
当てが外れることもあるから商売=ギャンブルは成り立つんだよ。
で、F#はどのへんで人気なの?
うるせーよ自分で調べろよ
じゃあHaskellはどの辺で人気なの?
人気なんてありませんよ。
人気がある言語をお望みでしたらどうぞお帰りください。
>>112 今の普通の言語だと
コンストラクタ
{
...
button.Click += button_click;
}
void button_click()
{
button.Text = button.Text + "*";
}
こんな風になるわけじゃない
こんなんと比較してどの辺が優れてるの?
カレーハワードの対応でリストに相当するもんはなんなんでしょうか
試しにzipwith :: (a->b->c)->[a]->[b]->[c]を場合分けで証明して、
そこからカレー(ry対応でhaskellのコードに変換したかったんですが
リストをどう処理していいのかわかりませんでした
よし、今日の晩飯はカレーだ
>>121 GUIの要素って、いくつかの入力といくつかの出力のある部品とみなせるじゃん
たとえばボタンなら、表面のテキストや、無効化されているかどうかの状態が入力で、クリックイベントが出力
Grapefruit(や、その他のFRPライブラリ)だと、こういう部品をいくつか繋げてより大きな部品を作る、という操作を簡単に
(定型的なイベントハンドリングのコードを手で書くことなく)行なえて、それを繰り返してGUIプログラムを書くことになる
個々の部品はそれぞれ独立して記述・テストできるし、プログラムの構造がGUIの構造を反映するから、保守しやすくなると思う
(小さいもの(たとえば関数)を組み合わせて順次大きいものを作るというスタイルが有効なのは、プログラマなら良く知ってるはず)
>>112の例だと、まずボタンの出力であるクリックイベントをscan(Data.List.scanlのアナロジー)を使って'*'の羅列に加工し、
それをボタンのテキスト入力にフィードバックした回路を作ってる
その回路がウィンドウに入っていて、全体として入力が空で出力がウィンドウを閉じるclosureイベントだけ、という回路になっている
あと細かい点として、部品の合成をするときは、部品の実体を直接繋ぐんじゃなくて、
部品の設計図(Haskellではアローで表現される)を合成して、最後に一括してインスタンスを作る
部品はコピーできないけど設計図はコピーできるので、扱いやすい
この設計図は通常の値なので、パラメタを指定すると設計図を返す関数、みたいなのも自然に書ける
こういう特徴をまとめてdeclarativeだというんじゃないかな…
>>125 良く分からんが、
zipWith f xs ys = []
という自明な証明がある自明な命題っぽい
Haskellerってやっぱゴリゴリアプリ作るよりも、論文読んで理論理解を進める
ことを主にしてるんですかね。
Haskellerって言っても色々いるだろ
俺はHaskellの論文読んでる時間よりHaskellのコード書いてる時間の方が圧倒的に長い
つうか論文ってどこで読むの (^ρ^)
haskell wikiにおいで
やっぱHaskellerってGHCのコードは全部読んだことあるの?
>>134 とりあえず手始めに
Simon Peyton Jonesのサイトにいくのはどう?
rts以外は全部読んだよ
>> 94
OCamlはオブジェクト指向があるからというより、単に実効速度が早いからじゃね?
型推論があって短く書けるし、コンパイルも早いし、
副作用もかけるからモナドが分かんなくても大丈夫だし
静的型があるから実行時の信頼性も高いし
サーバーサイドでOCamlは結構使われているんじゃないかなぁ。
でもOCamlの人はHaskell好きが多い気がする。
OCaml好きの俺は↑の通り速度+強い型付けに惹かれて始めた。
型推論の便利さは始めてから気づいたが
オブジェクト指向部分にはさして興味ない
Haskellはインデント強制と遅延評価が嫌いだが
それ以外の部分は、かじった程度には好きかなぁ
Common LispはわからんけどSchemeは好き。
C++のSTLさわるようになってちょっとたった頃
自分のやりたいことはC++では面倒だと悟って
Scheme→OCamlに至る
プログラミング習得の流れ
VB.net => C# => F# => OCaml => Haskell => Agda => Coq
もしくは
Java => Scala => Scheme => OCaml => Haskell => Agda => Coq
>>132 どんなコードを普段書いてるんですか?仕事で?
Real World Haskellは研究者の方から見るとどういう位置づけ
の本になりますか?
「新しいこと何もないじゃん。ツマンネ」って感じでしょうか。
>>145 ちょ、オレまだJavaだよ。まだまだだな。
>>145 右に行くほどWindowsに冷たくなっていくのがなぁ
関数型言語やり始めて初めてWindowsが嫌われる理由がわかったよ・・・
>145
ScalaとかOCamlとかやったことねぇw
OCaml速いの?Cleanの方が速いってイメージがあるけど。
Cleanってもうずっとメンテとまってるじゃん。
>145
確かにプログラムすごい人はみんな右側を目指している気がする。
現在のビジネス現場に用いられるかは別だけど。
158 :
デフォルトの名無しさん:2009/02/16(月) 01:47:40
Agdaもcoqも知らなかった
軽量スレッドとSTMとSIMD向き機能と
豊富なライブラリが有れば十分だと思う
いい線行ってるのは、Haskell,Clojure,F#じゃない?
clojure って、注目、集めてるのかな?
俺、ちょっと前、Webで引っかかって、
へ~と、思っただけだったんだけど。
Java ベースって所で、軽く読んだだけで
済ませちゃった。
Javaベース=ウンコ → 終了
>>160 なんでJavaベースでやろうとするんだろな。
Scalaとかそれだけで敬遠してるわ。
いいじゃん Java ベースでも。Clojure は実用性も強く意識
してる、いい言語だと思うよ。
>>164 Javaの仮想マシンが不安定なんです。
不安定って話は聞いた事が無いな。
ちょこちょこREPLを立ち上げる様な使い方だと、
相性が良いとは言えないとは思うけど。
GCがウンコなんで、Javaもウンコ。
もう仕様が悪いとしか言いようがありません。
・Java以外の言語でコーディング --> Javaバイトコード生成
・JVM(サーバ、クライアント共に)がきちんとクロージャなどをサポートするように進化
の条件が揃えば商用アプリ作成がしやすくなるんでは?
Java言語自体は衰退するかもしれんが。
>>166 おれも、Java だからという理由で気になるのは起動速度くらいだなぁ。
REPL といえば、ghci も起動速度遅いよね。hugs は早いの?
ぱっと見、興味を持ったとこ。
lazy-cons defn when-let あと、lisp-1
arcより、面白そうな気もする。
javaを嫌う人は結構いるだろうから、
もし、このlispがはやったら、
nativeで書く人が出てくるんじゃない。
けど、class library使えなくなっちゃうか。
Javaな時点でJavaを越えられないんだから夢が無いわ
CALの話が全く出てこないな…
>>166 起動してから3時間ぐらいスリープで無限ループしてからほかの処理をさせると、
いきなりエラーはいて終了することが良くあるんだけど原因は何なの?
今は史上初めて関数型がメインストリームに躍り出そうな瞬間、だね。
Java->Scalaと.NET->F#によって。
それでもJavaはJavaのほうが使われるだろうし
.NETはVB/C#のほうが使われるだろうけど。
マイクロソフトのおかげでJavaプログラマは激減の一途です。
まもなくJava終了のお知らせが来るでしょう。
>>174 F#ってギャグかと思ってたんですが、結構使われそうな雰囲気なんですか?
HaskellやOCaml知ってる人が現場で.Netで作ってね って言われても、C#、VBは嫌じゃね?
金儲けではF#, 趣味や研究ではHaskellってのがこれからはよくあるんじゃないかなぁ。
よくわからないんだけど、他人がソース読むこと考えたらC#は嫌とかいってらんないと思うけどなあ
結局関数型でないと見通しが悪くなったり、特殊なことがやりたいときくらいになるんじゃないかなあ
仕事でやるなら楽だから結構好き>C#
>>167 GCはもう文句をつける部分じゃなく、どうやって付き合って行くかを
考える部分だぞ。それくらい完全に浸透している。
しかもJavaVMのGCはかなり充実していて、バカに出来る物じゃないぞ。
特に並列GCについてはかなり頑張っていると思う。
>>180 GCの実装にはいろいろアルゴリズムがあるけど、Javaの仮想マシンに使われてるGCのアルゴリズムには苦情が多いよ。
付き合っていく以前に、Java自体衰退してるじゃん。既に。
アメリカじゃJavaが捨てられて混沌の世界になってるらしい。
>>181 どんな苦情があるの?
マルチプロセッサであれだけスケールしてくれるGCは他にはあまり無いし、
実装はきちんとしているイメージなんだが。
>>183 それは昔からの蓄積でしょ?
オープンソースが大きく取り扱われるようになった頃とJavaの流行が重なってるから、登録もその頃のものだろう。
もしくは商業ベースでのJavaプロジェクトがほとんど無くなったのでオープンソースに流れてきたのかな?
ともかくJavaが衰退してきているってよく聞くよ。
過去、C++が終わったという話をずっと聞き続けて来た気がするが、
『終わった事にする商法』はいつ終わるんだろうな…
プログラマは常にマーケッターに騙され続ける生き物
>>173 そんな話は知らんけど、ヘボプログラムだったんじゃないの?
暇を見て調べておくからエラーログと再現プログラムをくれ。
そろそろ Haskell の話題に戻ろうぜ↓
>>177 本当に「知っている人」はどんな言語でもちゃんと使えるよ。
半端な奴が「関数型じゃないとイヤ」とか言う。
私怨を持ち込む奴が半端物でなくてなんであろう
言語を作る人と言語を使う人(信者)の2種類いる
>>193 そいつただの実験厨じゃんw
実験厨は実験してるだけで実用的なアプリは作らないので
使われたことにはなりません
>>195のようなことを言う奴が実用的なアプリをつくっている例を見たことない。
>>196 実用的なアプリを作っている奴が
>>195のような書き込みをしたことがないという証拠がない。
>>197 あのさ、事実のあるなしじゃなくて、事後確率の問題なんじゃねーの?
統計にがてだった?
>>198 君ってどこまで負けず嫌いなの?
統計と言うなら数字を出すべきだし、それ以前に偏見を持って物事に当たるべからずっていう行間の意味が理解できないほど国語苦手だったの?^^;
実験厨のあとは同一認定厨が登場しました。次は何厨房が出るんでしょう?
なんだ、ただの釣り師か。
どうでも良いけど最近arrowの話題めっきり聞かなくなったな。
一時はすべてのhaskellライブラリがarrowで書き換えられるんじゃないかって勢いだったのに、
所詮は一過性の流行でしかなかったということか。
arrowへの書き換え作業が、なぜメインストリームに乗ると考えるかが不思議。
まぁ、実際arrowに書き換えないと乗り遅れるとみんなが思っていた時期もあった。
arrowが分かってない人だけじゃね
おじいちゃん、F#にのりかえたようですが
情報処理学会誌で、和田先生がHaskellのコラム書いてたのを思い出した
そのおじいちゃんすごいな、しかもForthちょうど今日完成したんだな。おめでたい
初心者です。
WIndows + Hugs でウィキペディアからデータをとるプログラムを作ろうとしているのですが、
いきなり文字化けでつまずいています。
module MediaWiki where
import System.IO
import Network
loop :: IO a -> IO a
loop a = a >> loop a
test = do
h <- connectTo "ja.wikipedia.org" (PortNumber 80)
hPutStr h "GET / HTTP/1.1\nHost:
http://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8\n\n"
f <- openFile "D:/test.txt" WriteMode
loop (hGetLine h >>= hPutStr f)
きちんとループ処理していないので、エラーで終了しますが、とりあえずデータは取れます。
しかし、文字化けしています。文字化けを回避する方法はないでしょうか。
自己解決しました。
お騒がせして、すみません…
>>214 テキストエディタ(Notepad++)が、コーディングをうまく認識しなかったようです。
メモ帳でUTF-8を指定して開くと読めました。
notepad++はやめときな。
あれはバグが多すぎて、書いたものや開いたものの安全は保障できないぜ。
winやったらxyzzyあたりでいいんじゃないの
xyzzyの機能はmeadowの劣化版だし、スクリプトに互換性ないでしょ。
使う気があるなら、ntemacsでもmeadowでも良いと思うよ。
ただ、notepadあたりを使ってる人に導入が簡単だろうか?
と思ったからだよ。notepadよりはマシだろ?
本当はemacsのhaskell-modeは欲しいね。
ghcって、バイナリ作るところまで担ってるの?それともアセンブラまで生成
して、アセンブルは外部に丸投げ?
アセンブルは丸投げ
GHCはCコードを生成してCコンパイラに渡す
>>220 アセンブラを生成って・・・
処理系を生成するわけじゃないんだからw
この文脈の場合は アセンブリ言語を生成 って言ったほうが誤解を招かないよ。
つうことはwindowsならgccでなくcl.exeを使うようにすることもできるのか
デフォルトはCを介さずアセンブリを直接生成じゃね?
少なくとも俺の環境(x86, Linux, ghc-6.10.1)だとそうだ
>>224 中間Cコードはgcc依存じゃないだろうか
gccが生成したアセンブリに後処理を加えてるくらいだから
アセンブラソースかアセンブリソースって言わないかな?
GCCのcc1もバイナリ生成しないし、自分の知ってる処理系では
MSC系とTurboC系ぐらいしかないな、直接オブジェクト吐く
コンパイラって。
じゃマシンコードで
turboC懐かしいなぁ・・ 初めて親に買ってもらったCコンパイラがturboCなんだが、もう20年も昔のことなのか。
このブルジョアめ…
金無くて、BASICでCコンパイラ書いてる奴も居た。
または8bitマシン語でメタコンパイラとか。
ghcもメタコンパイラと言えるんだろうか?
以前、川合史朗さんが書いたものだったと思うのですが、Haskellはトップダウン
なプログラミングでScheme(Lisp)はボトムアップだ、という話題を読んだことが
あります。
結局、Haskellの型チェックがコンパイル時に入るために、ごにょごにょと試しつつ
トップレベルの構造に至る、という作り方ができないんだと。
これってそうなんでしょうか。最初にピシッと構成が見えてないとプログラミングが
できない、ってのは不便な気がします。
>>223 ごめん、アセンブラリルの区別に自信なかった。
やっぱ間違ってたか。
>>232 Haskell だからってそんなことないと思うけどね。
Functional Parser のチュートリアルでよくあるじゃん。
プリミティブな部品(char とか)を作って、それを組み合わ
せて高度なもの(many とか)作って、さらにそれを組み合
わせて・・・っていう流れ。これってボトムアップだよね。
>>232 トップダウン、ボトムアップの部分は知らないけど、使っていて特にそう感じた事は無いけどなあ。
Haskellは多相型が強力なのと、未知の値->取り敢えずモナドに放り込む、未知の関数->取り敢えずArrow
で組んでいけるから構成が事前に固まっていなくても問題無い。
LISP系(Sheme、Gauche他)も、こんなオペレータがあればいいのにと思った時点ですぐ実装できる。
最初に構成が見えていないプロジェクトがやりにくいと感じるケースは、言語というより体制
(大人数・ウォーターフォールでやってて、コーダーに完成形の仕様書を渡す必要あり、など)に
原因ありの場合が多かった。
まあこれはC、Javaでも言える事なんで、むしろどんなケースで困ったのかが興味ある。
>>234 そのFunctional Parser自体をつくる時点でトップダウンという罠
>ghci
Prelude> let m3 x = 3 * x
Prelude> m3 5
15
Prelude> let m3 x = (*) 3 x
Prelude> let m3 = (*) 3
Prelude> let m3 = (* 3)
Prelude> m3 5
15
ここまではOK
Prelude> let mm x = x * x
Prelude> let mm = ?????
上記の?????が判らんorz
let mm = \x -> x * x
型限定版で
let mm = (** 2)
>>238,239
サンクス。 しばらく他(多)言語使ってたんでちょっと混乱してたw
>>234>>235 なるほど。自分はHaskellコードをそれなりの規模で書いた経験が無いので
実感できてないのかも知れないのですが、川合さんがおっしゃってるような
ことはよく感じちゃうんですね。
末端の補助関数みたいなものを、後からこのほうがいいな、と思ってちょっといじ
っただけで、バーっと型エラーになってしまうという。そうなると、最初にどうある
べきなんだろうか、とある程度の見通しを立ててからじゃないと手戻りが多い
気がしてます。
慣れの問題なんでしょうかね。
ここのエバンジェリスト ってだれ?
>>235 >Haskellは多相型が強力なのと、未知の値->取り敢えずモナドに放り込む、未知の関数->取り敢えずArrow
>で組んでいけるから構成が事前に固まっていなくても問題無い。
試行錯誤する例として短めのサンプルコードはあるでしょうか?
モナドやArrowを後から変更することはあるけど、
書き始める時点で全く未知ってのは、少なくとも俺の場合はないな。
実用性ってことでは、ライブラリに「なるほどこう使うのか」と分かるサンプルコードが付属しているのが大事だと思う。
オレがプログラミングで試行錯誤するのは、ライブラリの使い方が良く分からなくて、自分のやりたいことができるのか、どうできるのかを確認するのが大半のような気がするから。
素人です…
仕事で関数を使った表をやれと言われました
何にも知識無い人間でもできるもんですか?
>>246 言っている意味が分かりません。
excelの話ですか?
>>249 アルゴリズム的には、n < m の場合を考えてるのが変。
Haskell的には f の返り値が変。
f 1 _ = []
f n (m:ms)
| q == 0 = m : f b (m:ms)
| otherwise = f n ms
where
(b, q) = n `divMod` m
g n = f n [2..]
こんなんでました。
f _ [] = []
f n ps@(m:ms) = let (b, q) = n `divMod` m in if q == 0 then m:(f2 b ps) else f2 n ms
main = print $ map (\x->(x, f2 x [2..x])) [1..100]
252 :
251:2009/02/26(木) 03:48:33
数学的には 1 に [1] を返そうとしてるのが変。
>>249は末尾再帰の形にしようとして苦労してるように見える
Haskellだと直接consを返してもスタックが伸びていくことはないから、
consが返せるならその方が綺麗になることが多いし、逆にメモリ使用量が減ることもある
例えばmapの定義
map f [] = []
map f (x:xs) = f x : map f xs
は、呼び出し側が結果のリストを先頭から順に読み捨てていく限り、定数空間で動く
>>250 n < mのテストがないと再帰が止まらんだろ
>>250のコードでn == 1のテストをしてるのと同等
すごい読解力
返すのが ret だけなら末尾再帰にしようとしてるっぽいけど、
n や m まで返そうとしてるのは、単に関数型言語に不慣れなんじゃないかな。
257 :
249:2009/02/26(木) 19:50:35
皆様回答ありがとうございます
(_, _, a)とかでてくる時点でおかしいとは思ったんですが、随分綺麗に書けるものなんですね
>>249のコードは手続き型のループによる繰り返しを使ったアルゴリズムを元に考えたので
末尾再帰の形っぽくなったんだと思います
>>258 グレート! haskellはあまり触ってないけど、この件はもっと盛り上がってもよいとおもう。
262 :
デフォルトの名無しさん:2009/03/03(火) 22:52:37
この言語がメジャーになる日が来ると思う?
どうなったらメジャーになれると思う?
>>262 こっちの系統は。。。scalaのほうがウケそう。
こんかれんとはすける とかならありえそう?<じぇむす。ぶれーく
もっとポータビリティが向上すればok
yhcもっとガンガレ
>>264 そういえば、ghcってデカイよな。中性脂肪たっぷりってかんじ。
別にメジャーにならんでいい
メジャーになってライブラリの質と量が上がれば嬉しいけどなー
ライブラリ充実しても、普通に使えるようになるまでのハードルの高さが
ネックになってメインストリームにはならないんだろうね
メジャーになったらHaskellで飯くえるぞ (笑)
yhcがhaxeみたいになったらいい
Pythonのpy2exeみたく実行に必要なファイルをまとめて1個のexeファイルとかに出来ると良いんだけど。
>>269 メジャーになったら飯が食えるというのは幻想です。
良い物がメジャーになってない場合、市場規模は小さいから仕事を探すのは大変ですが、
特殊技能者として高給をもらえる可能性があります。
日本じゃないけど金融なら Haskell で 3000万円/year な所はありますよ。
飯食えんとか言ってる人はそもそも飯食ってやろうという覚悟のない人か、
現在の市場で雇われるにはまだ能力が足りない人。
メジャーになったらIT土方が大量に流入してくるので当然単価が下がります。
ま、Haskell で土方やりたいんだったらどんどんメジャーにしてくださいw
(まぁHaskell は比較的土方が流入しにくい構造にはなってると思うが。)
土方だって「飯は食える」よ。
ただIT土方は本物の土方と違って就業時間が厳しいが。
んなこと言ってるから買いたたかれて土方になっちまうんだよ。
cで土方やるよりhaskellで土方やる方がまだマシ
正直、どうやったらITドカタにならざるを得ない状況になるのか分からない。
就職口もシステムエンジニアか研究職ばっかりだし、派遣だったら一発で分かるし、ブラック企業って臭いで分かるし、
ITドカタの人に聞きたいけどどういう仕事探ししてるの?
最近、名刺は研究職だけど実態はドカタって人が増えてる気がする。
定時と同じかそれより早く帰れて、年間休日150日ぐらいあって福利厚生がよくて(ry
今なら仕事なくて定時帰宅多いんじゃね?
そうでもない
名ばかり研究職とか普通
隙間風がピューピュー、雨漏りしまくりのボロアパートでネズミをペットにして霞を食べていきてるっていうのが平均的な研究者の生活水準
小学生かよ
http://codepad.org/IjH5NT71 二引数のブール関数の引数とその戻り値の組み合わせを演算の定義とみなして
ある演算規則のもと、<=>と同じ結果を返すものでかつ<=>と同じ定義でないもの以外を探索するプログラムです
Haskellらしく書けてますか?
あと、もっとシンプルに書きたいんですがなんかいい方針とかありますかね?
286 :
285:2009/03/04(水) 18:39:57
上げてからMaybeの意味がないと気付いた…orz
土方土方言ってる人って何なのww?
蒸し返すお前から名乗れw
土方の話題を蒸し返して申し訳ないですが、現状の土方プログラマ業界に
Haskellが浸透したらかなり業界の風景が変わるんじゃないかな。
そもそもHaskell使っただけで、今までの命令型言語で発生してた途轍もない
ゴミコードを書き散らすことがかなり抑制されるわけですよね。副作用を利用
した手続きの羅列が禁じられてるわけだから。
逆に言えば、そうやって手続きをズラズラ書き連ねることでしかコーディングできない
人々は、Haskellで書くことになった途端思考停止になって何も書けないんじゃないか。
そして、元々命令型でも綺麗にコーディングできる人たちは生き残る。
そういう淘汰がすぐにでも起きてほしいと思ってる人は多いと思う。プログラミング
を仕事にするのが敬遠されるのは、結局はゴミコード製造機のお守りをさせられて、
賃金が能力に比例しないからでしょ。Haskellが普及したら変わると思うんだけどなぁ。
ゴミコードならすぐ上に上げられてるじゃないか
>>289 で、例えば現存するHaskellのGUIライブラリについてどう思う?
>>289 ゴミコードを書く奴はどんな言語を使ってもゴミコード書くんです。
>>290 じゃあ、どこがどうゴミなのか解説してあげて。 その一行なら誹謗中傷に等しいじゃないか
尋ねてきてる人に何言ってんだ。と思ったよ。
>>285 せっかくリストモナド使うなら、patternsはこう書ける。
patterns n = if n > 0
then do
ps <- patterns (n-1)
ft <- [False, True]
return (ps ++ [ft])
else [[]]
Haskellでも「副作用を利用した手続きの羅列」と同等な構造のコードは書けるし、書けないと困る
土方にHaskell書かせたら、引数が10個以上ある関数が山のように作られるだけ。
>>285 http://codepad.org/xbkr4jcX 特にどうということはないけど、
・isAssociative あたりの定義がおかしかった
・関数の場合しか考えてなさそうなので、
relation じゃなくて table にした
・一般化のバランスがおかしいと思った
(トップレベルにある fromListPair, db, search や DB型 とか)
>>298 allTable = [zip domain zs | zs <- patterns (length damain)]
のほうがいいのと、
>>285の意図は
p t = all (\q -> q (tab2op t) == q iff) ps where iff = (==)
っぽい
300 :
285:2009/03/05(木) 17:56:11
ありがとうございます!!
なんと行数が半分になるなんて…
sequenceやこの形でのパターンマッチは知りませんでした
最低でもPreludeだけは一通り触っておく必要性を感じました
もうイヤ
例えば g の関数を適用してから f の関数を適用するような関数を作るには単純に関数合成を行なえば良いわけですが、
> fg = f . g
g が2個以上の引数を受けとる関数の場合は引数を明示的に書く必要があります。
> fg x y = f (g x y)
ポイントフリーにすることも出来ますが、とたんにゴチャゴチャした書き方になってしまいます。
(Haskellには2個以上の引数を受取る関数など無い! という話もありますが、説明の便宜上のことなので 御容赦下さい。)
そこで、右側での適用を終えてから左側の関数へ適用するような演算子を定義できないものかと考えました。
> fg = f .$ g
こうすると g が2引数でも3引数でも対応できるような演算子 .$ があれば便利ではないかと。
で、以下のふたつの定義を考えてみたのですが、うまくオーバーロードさせるためのクラス定義がどうにも思い付きません。
> (.$) :: (a -> b) -> a -> b
> f .$ g = f g
>
> (.$) :: (a -> b) -> (c -> d) -> (c -> b)
> f .$ g = \x -> f .$ g x
「ふつうのHaskellプログラミング」を読み返してみるとクラス定義の説明がえらく簡単で、あんまりわからなかったんですが、
この本で説明されているHaskellの機能だけで実現できるものでしょうか?
>>303 Haskell 98 の範疇ではできないと思う。
下のような感じになるんだろうけど、
fundep が足りないのか、flexible や undecidable が悪いのか、
((sum :: [Int] -> Int) .$ take) 5 ([1..10] :: [Int])
のように型をはっきりさせないと no instance って怒られる。
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, UndecidableInstances #-}
class FApp a b f g | a b f -> g where
(.$) :: (a -> b) -> f -> g
instance FApp a b a b where
f .$ x = f x
instance FApp a b f g => FApp a b (c -> f) (c -> g) where
(f .$ g) x = f .$ (g x)
>>303 class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
-- Defined in Control.Applicative
ということ?
或いは、
ap :: (Monad m) => m (a -> b) -> m a -> m b
-- Defined in Control.Monad
のこと?
>>303 関数の型が与えられても引数の数は決まらないから無理だと思う
例えばconstは定数関数を作る一引数の関数として使うことが多いけど、型だけ見たら二引数関数に見える
idは型を見れば一引数関数だけど、Just `id` 4みたいな使い方も可能
妥協して純粋に型の「見た目」だけで引数の数を決定するなら、GHC拡張を使って実現できた
{-# LANGUAGE IncoherentInstances, OverlappingInstances, TypeFamilies, FlexibleInstances,
MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables #-}
module Curried where
class Curry f args result where
curryP :: (args -> result) -> f
class Uncurry f args result where
uncurryP :: f -> (args -> result)
instance (Curry rf as result, f ~ (a -> rf)) => Curry f (a, as) result where
curryP c x = curryP (\as -> c (x, as))
instance (Uncurry b as result, args ~ (a, as)) => Uncurry (a -> b) args result where
uncurryP f (a, as) = uncurryP (f a) as
module Main where
import Curried
instance (f ~ result) => Curry f () result where
curryP c = c ()
instance (args ~ (), result ~ f) => Uncurry f args result where
uncurryP f () = f
($.) :: forall f g a b c. (Uncurry f a b, Curry g a c) => (b -> c) -> f -> g
f $. g = curryP (\x -> f (uncurryP g (x :: a)))
-- テスト
main = print $ ((+1) $. const) 100 200
モジュールを分けないとコンパイル通らないあたり怪しげな匂いがプンプンするが
307 :
303:2009/03/08(日) 20:38:55
>>304 私が漠然と想像してた形に近いです。
型を書かないといけないのは、
sum とかはオーバーロードされてるからですかねぇ。
クラス定義のところのその型変数の書き方の意味がよくわかってないので、
まずはそこを学ばないといけないようです。
>>305 どちらも違うと思います。
今回、このような演算子があればよいなぁと思ったのは
Gauche にある compose っぽいのをイメージしてたのです。
.$ という演算子も Gauche で compose の別名として定義されてるので
そのままもってきました。
合成と適用をうまいことやってくれる演算子としてピッタリな気がしたので。
>>306 結構な大作をありがとうございます。
今の私ではそう簡単に理解できなさそうですが。
色々なオプションがあるんですねぇ。
> 関数の型が与えられても引数の数は決まらないから無理だと思う
> 例えばconstは定数関数を作る一引数の関数として使うことが多いけど、型だけ見たら二引数関数に見える
> idは型を見れば一引数関数だけど、Just `id` 4みたいな使い方も可能
Haskell で単純に引数の数を利用することは出来ないとは思っているので、
f .$ g で f を g に適用可能な場合には適用して、
そうでない場合には g をもうひとつ何かに適用してから、
という風な場合分けで考えてました。
関数コンストラクタ (->)って何か読み方あるんでしょうか?
♂の尖ってる部分
右って読んでる
やじるし
あろー
313 :
デフォルトの名無しさん:2009/03/13(金) 12:09:52
おめでとう
>>313 きみはこれから明い道が開いているよ
リストのn番目の内容を取り出すのはどうすれば良いですか
ls[n] じゃダメですよね?
ダメに決まってるだろ!!
自分で調べろよ!!
318 :
デフォルトの名無しさん:2009/03/14(土) 18:45:52
!!
お前ら優しいな!!
>316
ダメなのは判るのですが、それをHaskellでどう書けば良いのか判らないのです…。
>317
何でググれば良いでしょうか?
Preludeは一通り見たのですが、takeくらいしか見当たりません。
かと言ってリストをArrayに全部移すのも違うだろうし…。
>321
!!
英字の関数名ばかり見てました…orz
>316-319
何気に答えられていたことに気付きませんでした…すみません
ふグるとな・・・
ふぐりますか?ふぐりませんか?
エロサイトでも調べとんのかと思うぞ^^;<ふぐる
HaskellでSetの中身を指定した書式で表示したいときとかってどうするのでしょうか?
OCamlでは例えば(int, int)のTupleのSetをダンプしたいときはSet.iterを使って、
module TupleSet = Set.Make (...(省略)
let dump = TupleSet.iter (fun (a, b) -> Printf.printf "%d/%d\n" a b)
というようにできるのですが、HaskellのSetにはiterのような関数はありません。
私が思いついたのは、
import Data.Set (elems)
import Text.Printf (printf)
dump set = mapM_ (\(a, b) -> printf "%d/%d\n" a b) $ elems set
または
dump set = mapM_ (\(a, b) -> putStrLn $ show a ++ "/" ++ show b) $ elems set
というようなコードですが、もっとHaskellっぽいスマートなやり方があるような気がします。
要素を列挙するときに一旦リストを介するのは十分Haskellっぽいやり方だと思う
見た目を気にするなら
mapM_ (\(a, b) -> ...) $ elems set
より
forM_ (elems set) $ \(a, b) -> ...
の方がスマートかもしれん
あるいは、
dump set = putStr $ unlines $ map format $ elems set
where
format (a, b) = ...
みたいに、一番外側までしかIOを絡ませない方がHaskellっぽいかも
>> 328
レスありがとうございました。
確かにIOが途中で登場するより、最後に出てきたほうがスマートですね。
教えていただいたforM_からFoldableというクラスがあることを知り、そこからconcatMapが使えそうな気がしてきました。
リストモナドの(>>=)がconcatMapであることを利用して、今のところ
dump set = putStr $ elems set >>= format
where format (a, b) = ...
辺りまでたどり着きました。
難読化の好きそうな人だな
難読というほどのものでもないだろ
Fizz-Buzz問題をHaskellで書いてみました。どうでしょうか?
hoge :: Int -> String -> (Int, String) -> (Int, String)
hoge m s nt@(n, t) = if n `mod` m == 0 then (n, s ++ t)
else nt
fizz :: (Int, String) -> (Int, String)
fizz = hoge 3 "Fizz"
buzz :: (Int, String) -> (Int, String)
buzz = hoge 5 "Buzz"
piyo :: (Int, String) -> String
piyo (n, "") = show n
piyo (_, s) = s
fizzbuzz :: Int -> String
fizzbuzz n = piyo $ fizz $ buzz (n, "")
main = putStr $ unwords $ map fizzbuzz [1..100]
今日の一行 fizzbuzzでググれ
Haskell関係なく、(Int, String) -> (Int, String)を作るあたりがまわりくどいな
fizzとbuzz以外のルールを将来追加する可能性を考えてそういう形にしてるの?
それから、ググったら同じ構造のコードが出て来たんだが、引用元に批判を加えて欲しいの?
>>335 問題から素直に、fizz :: Int -> String で作ったら数字が出なくて
当てはまらない時は数字を返すようにしたら、5Buzzってなって
しょうがないのでタプルにしてStringが無いときは数字、あるときはStringにしました。
やっぱり一つの関数にして複数のifで分岐するような作りの方がいいのでしょうか?
たった三つの分岐だし、俺なら一つの関数内で全部やるな
それが嫌なら、
fizz, buzz :: Int -> String -- 該当しないときは空文字列を返す
みたいなのを用意して、
case fizz n ++ buzz n of
"" -> show n
s -> s
とか
あるいは、空文字列が技巧的だと思うならMaybeでもいい
>>332のアイデアで
module FizzBuzz where
data Fb = S [Char] | I Integer
instance Show Fb where
show (S s) = s
show (I x) = show x
hoge w n (S s) = S s
hoge w n (I x) | x `mod` n == 0 = S w
| otherwise = I x
fizzbuzz = hoge "FizzBuzz" 15
fizz = hoge "Fizz" 5
buzz = hoge "Buzz" 3
main = putStr $ show $ take 100 $ map (buzz. fizz . fizzbuzz . I) [1..]
>>337 アドバイスありがどうございます。case文は勉強になりました。
再帰の練習も兼ねて書き換えてみました。
hoge :: [(Int, String)] -> (Int, String) -> (Int, String)
hoge [] ns = ns
hoge (x:xs) ns@(n, s) = if n `mod` fst x == 0 then hoge xs (n, snd x ++ s) else hoge xs ns
piyo :: [(Int, String)]
piyo = [(3, "Fizz"), (5, "Buzz")]
fizzbuzz :: Int -> String
fizzbuzz n = case hoge piyo (n, "") of
(n, "") -> show n
(_, s) -> s
main = putStr $ unwords $ map fizzbuzz [1..100]
流れに乗り遅れた予感。
特に意味はないけどモナドにしてみた。
> import Control.Monad
> import Text.Show
>
> data FizzBuzz a = FizzBuzz String | Foo a
>
> instance Monad FizzBuzz where
> FizzBuzz a >>= k = FizzBuzz a
> Foo a >>= k = k a
> return = Foo
>
> instance (Show a) => Show (FizzBuzz a) where
> show (FizzBuzz a) = show a
> show (Foo a) = show a
>
> exam :: (a -> Bool) -> String -> a -> (FizzBuzz a)
> exam f s x = if (f x) then FizzBuzz s else Foo x
>
> x /? n = (x `mod` n) == 0
>
> fizzbuzz x = return x
> >>= exam (/? 15) "FizzBuzz"
> >>= exam (/? 3) "Fizz"
> >>= exam (/? 5) "Buzz"
>
> main = forM_ [1..5] (print . fizzbuzz)
素直にこんなんじゃいかんの?
main = putStrLn $ unwords $ map fizzbuzz [1..100]
where
fizzbuzz x
| x `mod` 15 == 0 = "FizzBuzz"
| x `mod` 5 == 0 = "Buzz"
| x `mod` 3 == 0 = "Fizz"
| otherwise = show
>>341 いいんだけど、それじゃ、盛り上がらんだろう
>>341 一つの関数でやるって話はずっと前から出てるだろ
main=mapM putStrLn[max(show n)$3%"Fizz"++5%"Buzz"|n<-[1..100],let(%)m=drop$n`mod`m*4]
darcsでは,かなり賢いパターンマッチを使ったパッチ当てが行われているのでしょうか
darcsはあなたの10倍程度賢いです
>>346 ほとんど神の領域ということですね わかります
そうです。神にもっとも近い言語です。
Haskellを極めれば、ほかの低俗な言語がクズに思えてきます。
Haskellはカルト
一部の人だけな
>>349 darcsは言語じゃねーだろ、アホか。
┐(´ー`)┌
遅延評価って無敵に最強なの?なんか弱点とかないの?
Haskellの宣伝を聞いているとアホな俺がなにも考えなくてもいいのかと思えてきました。
遅延評価それ自体のコストが大きいこと?
遅延評価自体のコスト…ですか。
それは実行時、それともコンパイル時でしょうか?
コストの種類は空間的なものですか、時間的なものですか?それとも処理系の複雑さでしょうか。
たとえば再帰でいう末尾再帰のように使い方によって差がでたりするのでしょうか。
ちょっとマンガ買うかHaskellの本の買うか迷ってまして。
実行時に時間的にも空間的にもコストがある
時間的コストはせいぜい積極評価の場合の定数倍だけど、ボトルネックにひびくこともある
空間的コストは慣れないとまったく予測できない。マジヤバい
初心者質問です。
タイプ宣言の時に関数を指定できると思います。
type T = String -> String
この時の"->"は型コンストラクタなんでしょうか。しかし、
test ((->) a b) = a ++ b
こういうのはダメって怒られます。"->"は特殊な扱いなんでしょうか。
それとも私の発想がどっかおかしいんでしょうか。
よろしくお願いいたします。
>>360 > test ((->) a b) = a ++ b
これが可能な型コンストラクタの例をあげてみて
runWriter >>> (printf "\nresult : %d\n" *** debugPrint) >>> uncurry (>>) $ foo 10 0
(IO a, IO a)をIO aにしようと思えばこういう風に結合するしかないんでしょうか?
m(m a)や[m a]をならすjoinやsequenceみたいなものがあると思うんですが
結合ってのは uncurry (>>)の部分でArrowの濫用をしているというところではないです。
しかし自重してかつリスプみたいにならないで済む方法があれば教えてほしいです。
haskell初心者にありがちなポイントフリー厨になっているというところは多少自覚しておりますorg。
>>359 読んでみたけど、入門以前な私にはちょっと難しかったです。
fstは組み込みの演算子でタプルの先頭を取り出すと理解しましたが、
一つ目の例だと先行評価の例でもコンパイル時に(\x -> fst (sum x, product x))を(sum x)
と最適化してから実行したらどうなのかな?と思いました。要するにCでいうこんなのかなと。
int t1, t2;
t1 = sum(x);
t2 = product(x); //副作用がないなら、これコンパイル時に消えるんじゃない?簡約というのは実行とはちがうのかな。
return t1;
二つ目の例だと、(やはりCとかを仮定すると)sumとproductの引数xは同一の変数というイメージがあります。
整数のリストへのポインタみたいな感じをもっていると、遅延評価の例で
「sumが0+1+2+3+4になったときのxをproductで使える」とどう嬉しいのかイマイチです…
よくわからないので、本読んでみることにしました。最初はテンプレにあるIntroduction to Functional Programming Using Haskellというのでいい?
>>364 > int t1, t2;
> t1 = sum(x);
> t2 = product(x); //副作用がないなら、これコンパイル時に消えるんじゃない?簡約というのは実行とはちがうのかな。
> return t1;
コンパイル時に消えるかどうかはコンパイラの実装依存だと思うけど(GHCだとどうかはもっとエロい人、お願い)、実行時にはproduct(x)はHaskellでは評価されない、という話がそのページに書いてある。
Cでも、product(x)が副作用がないっていうことが分かっていればコンパイル時に消えるだろうけど(GCCではそんなマークがつけられたような…)、それは普通は分からないし、原則的に副作用があると仮定されている。
つまり、デフォルトでは、副作用ありだと考えていちおう実行するのがC、副作用なしだと考えて実行しないのかHaskell、ということ。
べつに、Cでもコンパイラの特殊な拡張構文とかを使って副作用なしマークを付けまくるぜ、というのであれば、この点に限ればたいして違いはないと思う。
> 二つ目の例だと、(やはりCとかを仮定すると)sumとproductの引数xは同一の変数というイメージがあります。
> 整数のリストへのポインタみたいな感じをもっていると、遅延評価の例で
> 「sumが0+1+2+3+4になったときのxをproductで使える」とどう嬉しいのかイマイチです…
これは、Cだと当然そうで、Haskellのほうがすごいわけじゃない。
ただ、Haskellへの誤解として、
(\x -> (sum x, product x)) [0..5]
=> (sum [0..5], product [0..5])
=> (sum [0,1,2,3,4,5], product [0..5])
=> (15, product [0..5]])
=> (15, product [0,1,2,3,4,5])
=> (15, 0)
という評価をしている([0..5]が二回評価されている)という誤解がありえるから、それを否定しているわけ。
Cと同じ(というか正格評価と同じ)オーダで計算できますよ、ということ。
fun of programming からの問題についての質問です。
newtype Except a b c = E(a b (Either String c))
instance ArrowChoice a => Arrow (Except a) where
↑この定義を求めよ、という問題がありますが分かりませんでした。Arrowに
Stringの例外を挿入するということなんですが、挫折しました。
どうかよろしくお願いいたします。
個別スレがないのでここで聞いてみますが
lazy-k(もしくはunlambda)をラムダ式にしてくれるような変換器って
どっかにないでしょうか
>>366 本当に興味から聞いてみたんだけど、定番の宿題だったのかな
それはすいませんでした。とりあえずPogramming in Haskellを買いましたよっと
>>367 書いてみた。添削希望
import qualified Control.Category
import Control.Category((>>>), Category)
import Control.Arrow
newtype Except a b c = E (a b (Either String c))
instance (ArrowChoice a) => Category (Except a) where
id = E $ arr Right
E g . E f = E $ f >>> (arr Left ||| g)
instance (ArrowChoice a) => Arrow (Except a) where
arr f = E $ arr (Right . f)
first (E a) = E $ first a >>> arr combine
where
combine (Left e, _) = Left e
combine (Right x, y) = Right (x, y)
riみたいにコンソールからドキュメントを参照できたらいいのになぁー
それがあればemacsからdescribe-functionとかfind-functionみたいに
コードから一発で飛ぶとかできて便利になるのに…
372 :
367:2009/03/27(金) 20:16:35
GHC 使ってて気付いた。
breakEnd ってリストとか ByteString に使えるやつはあるんだけど、
String バージョンは無いの?
fromString って何の意味があんの?
read があればいらないんじゃね?
役割が違うだろ
read "\"foo\"" :: String
= "foo"
fromString "\"foo\"" :: String
= "\"foo\""
Parsecみたいにコンビネータで柔軟に書式を構築できて
コンパイル時に書式をチェックできるようなprintfはありませんかね?
%4dみたいな数字の表現が辛いから無理なんでしょうかね
>>377 いいたいことがよくわからん。
コードで例を書いてくれ
>>378 int_ @ alighLeft 3 >> ", " >> str_
から(\n s -> take 3 (show n++repeat ' ') ++ ', ' ++ ", " ++ s)
みたいな関数を返すような演算って絶対誰か考えてる筈だなと思ってました
>>379 それです
unparsingっていうんですね、その考えはありませんでした
382 :
303:2009/04/05(日) 20:47:13
>>304 どこかに forall を入れれば良いような気がしてきました
cabalでパッケージ入れる時にldが200mbぐらい実メモリ喰うんだけど
これって普通なの?
よくあること
興味があるならdocumentを作るようにして、でかいパッケージでも入れてみな
haddockが700Mとか余裕で食うから
385 :
383:2009/04/12(日) 23:32:02
遅延評価勉強法ってありますが、自分の場合Javaとかはそれで学習しました
けど、遅延評価言語Haskellは何故かできませんでした。
最初は戯れ的にやってたんですが、教科書最初から読まないと結局ダメ
だったです。これって自分固有なんでしょうか。
何かHaskellとかが普及しない原因が、遅延評価勉強法が通用しない、
つまりいい意味で適当に書くことができない、ってことはないんですかね。
量産型あまちゃのつ
俺もそうだった
そもそも自分の知ってるものとぜんぜん違うものを学ぶときは教科書を最初から読むもんじゃないか?
普及しない原因の一つではあるかもな
新しい機能を使うのを遅延するためには、
代替手段として古い機能が残されていなければならないからね。
真の遅延評価であれば、Haskellが必要になるまで勉強しない
つまり、一生しないわけだが
悲しいこと言うなよ
俺はここの機能はJavaのアレと比べてどうなんだ!って興味から入ったな
型推論とか、継承とパターンマッチとか、型クラスとか、
そういうとこから入って最終的にモナドがどうのとかやってた。
ちょうど大学で離散数学をやってたのもいい刺激になった。
遅延評価勉強法といってもコード書かないと勉強したことにならんわけではないので
そういうのでもいいんでないかな?
>>388 確かに最初に概要を知らないと手がつけられないというのはあると思います。
だけど、Haskellの場合は何か違うんですよね。本当にちゃんと教科書を最初から
読んで、知識を積み重ねていかないとダメだったんです。他の言語の場合は
適当に概要を流して、あとは作っていきながら覚える、って感じだったんですけど。
IOまでの道のりが長いからかな
>>394 そもそもHello, Worldって言語ごとに癖の強い部分が出るから困る
CのHelloWorldは可変長引数だし、
C++のHelloWorldは変態な演算子オーバーロードだし、
C#やJavaのHelloWorldはドット大杉クラス変数だし
ほかの言語も文だったり式だったり関数だったりメソッドだったり。
ついでにstd::coutとかがグローバル変数になっているのも
レジストリがどうのとか特殊な方法で実装されているもので、
その点ではHaskellのprintStrLnとかとどっこいのような気がする
>>395 Lispなどの経験者じゃなくて、CやJavaからHaskellで「遅延評価勉強法」ができた、
というのは凄いと思います。
自分が教科書をきちんと読もう、と決意したのは、Haskellの記述方法云々では
なくて、例えばfoldって何なんだとか、そういう関数型文化を知らなかったから
というのはあります。
ただ、それだけじゃなくて、関数型でコード書く場合には宣言的であることを強要
される感じがするんですよね。例えば中学生が文章題の数学の問題解く場合に、
文書に従った手続きは分かっても、そこに書かれていることを方程式にせよ、
って言われた途端に思考停止する子とかいますよね。
Haskellで書くときはそういう感覚になります。そうなると、適当にずらずら書くことは
不可能で、きっちり勉強してないと難しいと思うんですがどうなんでしょうかね。
敷居の高さはその辺にあるんじゃなかろうかと思うんですが。
全てが副作用無しである必要はないと思うんだよ
ピンポイントで正しいと判定できれば
モナドみたいな屁理屈使って無理矢理全てに適用するなんて
ナンセンスだと思うね
命令的なコードを書くならモナドがあれば十分なのに、副作用なんていう謎なものを持ち出すのがナンセンスだよ
関数適用を入れ子にすることをずらずら並べると言おうと思えば言えるけど、そういうことじゃない?
宣言的かどうかという面でいえばオブジェクト指向だって(手続き型と比べれば)宣言的だよね。
そうするとまともなオブジェクト指向も敷居が高いといえるのかな?(オブジェクト指向言語を手続き型的に使ってる?)
>>399 >ピンポイントで正しいと判定できれば
そのためにunsafeな関数やFFIが用意されてると思うんだけど
IOモナドがモナド則(associativity)を満たしているというのがいまだに腑に落ちない
>>401 まぁ、関数型でもそう書けるとは思いますが、難しくないですか。
あと、仰る通りでオブジェクト指向で綺麗に書けているコードは宣言的ですね。
だけど、これをいきなり書け、って入門者が言われれば敷居は高いんじゃ
ないでしょうか。Javaなどはその辺の逃げ道がいくらでもあるわけです。
Haskellには逃げ道無いんですよね。
副作用を許す→等式推論が死ぬ程難しくなって初心者お断り度がさらにうp
>>403 上手く言葉が整理できないんだけど。
手続き型言語のIOを例えるなら、
虫籠を用意して、クワガタを取りに行くようなものになる。
この場合、クワガタを取りに行って虫籠を用意するのはおかしい。
副作用があるばあい、順番が変わるとおかしなことになるってわけだ。
そこで、IOモナドは評価された瞬間に副作用のある行動はせず、
副作用のある行動の予定をリストにし、bindによってその予定リストを構築する。つまり、
「() -> IO 虫籠」>>=「虫籠 -> IO クワガタ」
のようなIOモナドは、内部では、
「((), 空の予定リスト) -> (虫籠, [虫籠を用意する予定])」>>>
「(虫籠, [虫籠を用意する予定]) -> (クワガタ, [虫籠を用意, クワガタを取りに行く予定])」
おそらくこんな感じになっているので、
前の関数から簡約されても、後ろの関数から簡約されても結果は同じになり、
[虫籠を用意する予定, クワガタを取りに行く予定]が最終的な予定リストになる。
この予定リストをプログラム終了後に手続き的な処理系に渡して実行すればIO処理ができる。
>>406 その例でループや条件分岐が発生したら
どこに組み込まれるんですか?
虫籠みつかったY→クワガタ取りにいく
N
↓
探しなおす
人工知能用語でいうところの状況計算
>>407 条件分岐やループが入ってくると
>>406みたいな予定リストのアナロジーでは説明が付かなくなるな
IOモナドがモナド則でいう結合律を満たすのって、副作用のある言語でも関数合成が結合律を満たすのと同じことじゃね、と思って、
comp :: (b -> IO c) -> (a -> IO b) -> a -> IO c
の結合性を仮定して
a >>= b = comp b (const a) ()
がモナド則を満たすことを証明できるかと思ったけど俺には無理だった
>>409 じゃ、LispのS式のようなものはアナロジーにならないかな。
HaskellにとってS式はただの木構造でしかないわけで、どこから作っても同じS式が出来上がる。
S式の評価順序には意味があるけれども、それはHaskellとは別の処理系が実行するから全然問題ない。
あとさ、関数合成がある言語でも副作用のある関数を使えば結合則は満たさないよ。
IO aをState RealWorld aとして
StateMonadがmonad lawを満たすことを利用してすれば証明できそうな気がせんでもない
もう少し考えるわ…λ
分岐やループはArrowを持ち出すとなんとかなるのかな?
>あとさ、関数合成がある言語でも副作用のある関数を使えば結合則は満たさないよ。
結合則が破られる例ある?
関数合成の結合則って
(f . g) . h = f . (g . h)でしょ?
両辺ともf(g(h x))に簡約されるんだから、これが同じ値にならないってのは
結合則とか関係なしに単に参照透明性を持たないってだけなのでは?
難しいこと考えるの好きだよな
415 :
デフォルトの名無しさん:2009/04/18(土) 13:43:56
モナドごてごてでも良いからDelphiみたいなRAD環境がHaskellにも欲しいです。
Haskellで楽にWindowsアプリの開発できる日は・・・来ないですよね・・・orz
あと、標準でUTF-8(Shift-JISとまでは言わないから・・・)表示できるようになって欲しい・・・
>>415 作ってる人はいるよ。
Eclipseのプロジェクトとかなかったっけ?
417 :
デフォルトの名無しさん:2009/04/18(土) 15:13:38
本当ですか?
詳しく教えてもらえると助かります。
今はWindowsGUIはC#で作ってますが、Haskellで統一できるならそうしたいです><
インタラクティブなプログラムを書きたいならHaskellはまだ準備不足だと思うねぇ。
まだHaskellは下地作りの段階で、実用としてバンバン使っていける段階じゃないよ。
だいたい方向性が定まったぐらいの段階かな?
並列・並行処理路線ってやつ。
いつそんな路線が決まったんだw
DelphiみたいなRADじゃないけど、gtk2hs+gladeじゃダメ?
Unicodeに関してはData.TextチームがStream Fusionを使ったライブラリをリリースしたよ
まだ実用としてバンバン使うわけにはいかないけど
421 :
デフォルトの名無しさん:2009/04/18(土) 17:08:24
>>420
RADじゃないGTK2hsは名前は知ってるんです。
時間が有れば勉強してみるつもりですが・・・
結局コードをゴリゴリになりますし、手続き的なコードがまる見えなので・・・・
RADならそういうコードが見なくて済むのに・・・と^^;
やっぱりRADはまだ無いですよねぇ^^;
>>418
まだ実用的なのは作れないでしょうけど、どうせ私は趣味でやっているのでお遊びのゲームアプリとか作るのにDelphiみたいな環境で作れたら積極的に作っていこうと考えていたんですけど・・・
やっぱりVisualC#やDelphiでメインで開発してHaskell+GTK2hsは勉強用になりそうですね^^;
全角に寛容な涼スレ
423 :
デフォルトの名無しさん:2009/04/18(土) 17:44:57
>>418 あ、実用的じゃないのはUnicodeの方もでしょうか?
だから自己責任で手動で入れろと言うことなんでしょうかね?
私が言いたかったのは標準で(何も入れなくても)Unicodeで日本語が表示できる日はまだかなぁ・・・と^^;
RADはいらんが、ステップ実行できるデバッガが欲しい
なんて手続き型なw
GHCiぐらいまともに使いこなせ
Hindley-Milnerよりも理論的に良い型システムってありますか?
これを拡張したら
何となく、主型が一意に決まらなかったりしそうに思うけど
個人的にlispに浸かるのが嫌なのでemacsを越えようと頑張ってるYiに期待している。
キーバインドがemacsモードとviモードと選択できるのも面白い。
シンタックスハイライトの書き方とかドキュメントがもっとあれば弄ってやりたいけど、まだまだHaskellを操れないから指咥えて見てる。
430 :
デフォルトの名無しさん:2009/04/21(火) 23:02:46
ごめんなさい。
Yiを知らないのですが、Lispに浸らないなら、何に浸るのでしょう?
まさか、Haskellに浸れるのでしょうか?
だったら私も応援したいです><
431 :
デフォルトの名無しさん:2009/04/21(火) 23:03:49
Yi で ESC キーをメタキーに設定するやりかたがわからないおれはまけぐみ
432 :
デフォルトの名無しさん:2009/04/21(火) 23:26:01
VC2005 C++/CLIの構造体の構文が知りたいです。
strcut A {
Int32 hoge;
String^ moe;
};
は構文エラーでしょうか?
定義する場所も知りたいです。
HSDLもhsSDLもビルドは出来て、ライブラリのインストールまでは出来てるんですが、
リンカエラーが出ていて困っています。
E:/test/hoge.o(.text+0xb21):fake: undefined reference to `__stginit_hsdlzm0zi2zi0_MultimediaziSDL_'
やったことは、こんな感じです。
①cabalの修正(includeとかlibとか)
②runghc setup.hs configure
③runghc setup.hs build
④runghc setup.hs install
⑤↓これをコンパイル
import Multimedia.SDL
main = putStrLn "hoge"
更に、他の関数も色々使い始めると、リンクエラーとして、こんなものも出てきます。
E:/test/hoge.o(.text+0x98e):fake: undefined reference to `hsdlzm0zi2zi0_MultimediaziSDLziInit_sdlQuit_closure'
コンパイル環境はこんな感じです。
GHC 6.8.3 SDL 1.2.11 / 1.2.12 / 1.2.13
GHC 6.10.2 SDL 1.2.13
このエラーに何か心当たりある人いませんか?
>>434 コンパイルオプションに" --make"を入れても駄目?
>>435 まさしくそれでした(;´Д`) ありがとうございます。
--make入れないとライブラリ見に行ってくれない、っていうことでしょうか…。
--make使わないならリンク時に-packageオプションが必要なんじゃなかったっけ
Yiもいいかもしれんがleksahもいいな。
forall aと打ったら∀ aと表示される。
++は⊕になるし>>としたら≫になるし>>=は↠になる。
ソースコード開いたら数学記号が出てきて一瞬ビビるが、中々面白い試み。
試したいんだけど
leksah: error: a C finalizer called back into Haskell.
use Foreign.Concurrent.newForeignPtr for Haskell finalizers.
って出て落ちちゃうんだよね…orz
>>438 言われて気づいた。
\x -> は、λx →になんのね。
darcs headだと落ちないみたい
でも表示変えるぐらいならemacsでもできる
cygwinからhaskell-mode使ってる人いますか?
C-c C-lで渡されるCygwinのパスをghciが認識しないため
:loadでエラーが出るのですが
なんかいい解決策ありますかね
elispわからないので
cygpathについて調べて.emacsやらを改良するってのは
私には無理そうです
ググって解決しました
inf-haskell.elに追加
(defun get-cygwin-path (x) "translate cygwin path into windows path"
(let* ((x (concat "cygpath -wa " "\"" x "\""))
(y (shell-command-to-string x))
(z (substring y 0 (- (length y) 1)))
(w (replace-regexp-in-string "\\\\" "/" z)))
w))
;haskell-load-file関数の以下の箇所を修正
;(file buffer-file-name)
(file (get-cygwin-path buffer-file-name))
>>438 emacsのhaskell-modeでもできる。
customizeでhaskell-font-lock-symbolsをunicodeにすると、
not が ¬
-> が →
<- が ←
=> が ⇒
~> が ⇝
-< が ↢
:: が ∷
. が ○
forall が ∀
になる。
はい はい APL APL
Haskell基礎的なものは一応勉強したんですが、実際のコードとか見ると、結構
GHCの型関連のオプションが必要になりますよね。
こういったオプションに関する資料でよくまとまったものが読みたいのですが、
GHCのドキュメント以外には何かよいものはありますでしょうか。
haskell wiki
foldr1 f . g = foldr1 h
という合成で、
h x y = foldr1 f (g [x,y])
と置けばなんとなくできそうな気がするんですが、
これがどういう時に成り立つかまでが出せません
とりあえず g[x] = [x]は出るんですが、残るfとgを両方含む等式では
何度計算しても
g (x:xs) = g [x, foldr1 f (g xs)]という変な式しか出ません
[x]と(x:xs)を放り込んで簡約していく以外の方法で簡単に出せるものがあるなら紹介してください
よく知りませんがhyloとか言うのを使えば楽に出せたりするんでしょうかね?
449 :
448:2009/05/03(日) 21:54:32
ちなみに出展はIntroduction to Functional Programming Using Haskellの137ページ4.6.8です。
この章の他の問題はなんとか解けたんですがこれだけさっぱりわかりません。
とりあえず、この問題
foldr1 f . scanl1 g = foldr1 hという合成をする為に
foldr1 f . g = foldr1 hという式を導き出すという方針でいける筈ですが、
この式が出せないという…
質問の意味が分からない
何かを求めたいの?何かを証明したいの?
451 :
448:2009/05/03(日) 22:38:03
>>450 わかりにくかったようですねすいません
一言で言ってしまえば、
foldr1 f .g = foldr1 hにおいて、
この式が成り立つ条件ってのを求めるのが目標です
あと、その定めた条件下でこの式がなりたつことの証明もやりたいです
うーん・・・
いわゆるVector3とかを定義するにはどうするのがよいですかね?
data IVector3 = IVector3 Int Int Int
みたいに定義することも出来るし演算も定義は簡単だけれど
この方法だと次元ごとにデータ型を特殊化しなきゃならなくて美しくなさすぎる…
といってリストとかタプルじゃ根本的解決にならないしなぁ
>>452 タプルが普通だと思う
名前がつけたいならtypeとかnewtypeとかすればいいじゃん
{-# OPTIONS -fglasgow-exts #-}
data Z
data S n
data Vec len where
Nil :: Vec Z
(:::) :: Int -> Vec l -> Vec (S l)
infixr 1 :::
instance Show (Vec Z) where
show _ = "[]"
instance Show (Vec n) => Show (Vec (S n)) where
show (i ::: v) = show i ++ ":" ++ show v
>>454 Vec上のfilterにはどんな型がつくんですか?
456 :
448:2009/05/05(火) 02:04:14
foldr1 f . g = foldr1 hというものに拘らずに、直接foldr1 f . scanl1 g = foldr hを計算したら
h x y = f x (g x y)かつ
x * (y + (y * z)) = (x * y) + ((x * y) * z) where (+) = f ; (*) = g
すなわちgがfに対して分配でき、かつgが結合的であるとき
という条件が出てきました(当然、対象になるリストが非空であるときというのも条件です)
これはfoldr1 f . scanl g = foldr h eという合成のときの条件とほぼ同じで、かつ
fにmax, gに+を代入すると+両辺ともにx+y+zになり4.6.9で使える結果となり
それっぽいなとは思うのですが、いまいち釈然としませんね
「fusion law of foldr1」はどこに行ったのでしょうというか…
458 :
448:2009/05/05(火) 08:26:56
zが負のときを忘れてました
でもy<0 -> x `max` (x+y) = xを使うと両辺ともx+yに簡約され
f = max, g = (+)のとき件の規則による書き換えが有効ってことには違いありませんね
haskellで不便だと思う分野って何?
その辺のライブラリを勉強で作ってみようと思うんだけど
GUIとか?
>>459 俺には理解できないこと
俺 バカ 普通 ハッカー ウィザード
┝ - - - - ┿━━━┿━━━┿━━━┥
∩___∩ /)
| ノ ヽ ( i )))
/ ● ● | / /
| ( _●_) |ノ / ここら辺クマ……
彡、 |∪| ,/
/ ヽノ /
>>459 コンパイルが遅いこと
GCばかりすること
463 :
デフォルトの名無しさん:2009/05/13(水) 22:53:35
コンパイルの遅さやGCの頻発はライブラリで解決するものなの?
>>461 一般人<バカ<普通<神<ハッカー
ウィザード?は?
>>463 ライブラリはむしろ、それらに依存するものだよ。
>>459 yi 用 plugin の has2ch
ライブラリじゃないんだけど、
haskellのsource file の保存場所を指定する仕組みが欲しい。
cabal で、package 毎に階層のTopを指定するとか、
.hiファイルに元ファイルの場所を書き込んでおくとか。
cabal install でソースも一緒にインストールしてくれると楽なんだけど。
HXT格好いいですね
directoryのtraverseも同じようにArrowTreeを使って抽象化できないものなんでしょうかね?
yiってemacsおきかえるぐらい発展しそうですか
committerがemacsと同じくらいの人数まで増えればあるいは…
↓こんな感じのモナドつくってみたんだが、200MBくらいのファイル読んだだけでスタックが溢れる(´Д`;)
なんかうまく回す方法ないでしょうか…
mapper :: [(Int, String)] -> WriterT (D.DList String) IO (M.Map Int Int)
mapper [] = return M.empty
mapper ((n,cs) : rest) =
if cs == "" || not (all isNumber cs)
then tell (D.fromList ["Impurt Error at line : " ++ show n]) >>
mapper rest >>= \result -> return $ (-1, 1) `upsert` result
else mapper rest >>= \result -> return $ (read $ cs :: Int , 1) `upsert` result
where
upsert (k, v) m =
if k `M.member` m then M.updateAt (\k' v' -> Just $ v'+v) k m
else M.insert k v m
newtype DList a = DL {unDL :: [a] -> [a]}
append xs ys = DL (unDL xs . unDL ys)
empty = DL id
instance Monoid (DList a) where
mempty = empty
mappend = append
appendの定義をundefinedにしてもスタックオバ風呂になったから
mapperの方にも問題はありそう
特にrec >>= fてのから危険な臭いがする
とりあえず、foldl'で書くことを試してみてはどうだろうか?
>>471 updateAt の第2引数はマップ内のレコード番号でキーとは違うけど、それはわかってるかな?
本当は insertWith (+) k 1 じゃない?そうだと(つまり数字の出現回数をカウントしたいんだと)
したら、素直に頭から処理する末尾再帰の形にすればいいと思う。いまのだと
>>472の言うように
mapper rest のせいで入力レコード数分スタックを積んじゃってるから。
474 :
471:2009/05/18(月) 20:55:27
>>472,473
あー理解できました
わざわざトレースしてくれてありがとう
とりあえず(insertWith (+) k 1に直したうえで) foldl' で (M.empty, D.empty) に畳み込んだらうまくいったので
明日は末尾再帰を試してみます
Haskellは宣言的言語でhowでなくwhatを書く、
とかいいだしたのは誰なのかしら?
そんな当たり前のことを誰が言ったか気にする人いるの?
コロンブスの卵
478 :
デフォルトの名無しさん:2009/05/19(火) 04:20:13
ブスの卵
当たり前どころか嘘じゃね?
>>479 お前は馬鹿か?
どこがどう嘘なのか言ってみろ
HowじゃなくてWhatっていうのはHaskellじゃなくて
Haskellを含む関数型言語のコミュニティに強い影響を与えている
Bird-Merteens formalismという考え方における目標なんじゃないのかな?
>>481 だけど、Haskellの最初の10年くらいの大方の評価は
「Prologに似ている関数型言語」だよ。その時点で
宣言型で誰も文句はなかったんじゃないの?
> Prologに似ている
初耳
>>483 遅延評価のKRCがそっくりだったから。その後、統合して
Haskellが出てきたと受け止められた。あっPrologに似てるな
というのが私や仲間の印象だった。
485 :
484:2009/05/19(火) 17:42:12
ごめん。KRCがHaskellに似ているのではなくてPrologに似ていた。
いまErlangを見るより、KRCの方が似て見えた。その流れだと
Haskellは受け取られ、先入観もあるかもしれないが、あっやっぱり
Prologに似てるなと思った。
>471-474
のやりとりをみると、宣言的? となる気持ちはわかる。
まあprologでも大差ないが。
普通の人はMirandaやGoferと似ていると思っただろ。
Prologとか斜め上すぎ。
>>487 そりゃ、普通の人じゃなくて関数型言語の研究者でしょ。
で、こん中でMirandaでプログラム書いたことある人ってどんくらいいるの?
>>489 実際に動かしたことはないけどワドラーの「関数プログラミング」読みながら
コード書いたことはある
そのときPrologに似てると思った。パターンマッチングのせいだろうけど
論理プログラミングや関数型プログラミングは、宣言的プログラミングの
サブカテゴリだぞ。
foldl' でもまだループごとに未評価の式(マップへのインサート)が溜まってる模様
(Mapをつくる関数は無事に終了するもののその後Mapを評価しようとするとスタックオーバーフローに)
↓最終的にこんなんつかったらどうにかなりました
import Control.Parallel.Strategies
instance NFData (DList a) where rnf = \_ -> ()
foldlRNF f acc xs = helper acc xs
where
helper a [] = a
helper a (x:xs) = helper a' xs
where a' = f a x `using` rnf
>>489 学部生のときMirandaネタで卒論書きました。
入力されたテキストの、行頭の1つ以上連続した半角スペースを
同じ数の半角の &nbsp; という文字列に置き換える
…ってHaskellで書くとどうなりますか
main = interact $ unlines . map processLine . lines
processLine :: String -> String
processLine ln = nbsps ++ rest
where
(ws, rest) = span (==' ') ln
nbsps = concat $ map (const " ") ws
このスレの平均年齢って?
大学学部生以下お断り
>496
を~、知らない関数がたくさん…読み込んでみます
500 :
473:2009/05/21(木) 06:09:01
>>492 モナドなし、再帰版。出力の形式はWriterTのように計算結果とログのタプル(ペア)です。
mapper :: [(Int, String)] -> (M.Map Int Int, String)
mapper seq = let res = mapperHelper seq M.empty (D.fromList "Log:\n") in
(fst res, D.toList $ snd $ res)
mapperHelper :: [(Int, String)] -> (M.Map Int Int) -> (D.DList Char) -> (M.Map Int Int, D.DList Char)
mapperHelper [] mon log = (mon, log)
mapperHelper ((n, cs) : rest) mon log = mon `seq`
if (all isNumber cs)
then
mapperHelper rest (M.insertWith'(+) (read cs :: Int) 1 mon) log
else
mapperHelper rest (M.insertWith' (+) (-1) 1 mon) (log `mappend` D.fromList ("Error at line " ++ show n ++ "\n"))
>>499 これはそんなに難しくないよ。
main は標準入力から受けたテキストを、
1. 行ごとに分けて (lines)
2. 各行を変換して (map processLine)
3. 各行をつなげる (unlines)
processLine は一行のテキストを変換するわけだけど、
1. 先頭からのスペース続きの部分と、それ以降の残りの部分に分けて (span (== ' ') ln)
2. スペースの部分を に変換して (concat $ map (const " ") ws)
3. 変換したところ (nbsps) と残りの部分 (rest) を繋げる (nbsps ++ rest)
放り出してたところに回答が…
ありがとうございます(`・ω・´)
いろいろ連れ回して再帰するってのが手続き脳にはつらいんだなあ、と実感
503 :
473:2009/05/21(木) 23:33:16
末尾再帰最適化というのはgotoをカッコ良さげに読んでみただけです。
haskellのlazinessやモナドの合成と相性が悪いのでそこは気をつけないといけませんが。
>>496 は今後投稿する時に使わせてもらうか
いや俺の場合、今までもPythonでやってたけど…。
バイナリファイルのパーサーで効率よい方法ないですかね?
C言語なら構造体ぶち込んで終了みたいなところが結構だるいんですが…
struct Hoge
{
data Hoge = Hoge Word32 Word32 [Word16]
>>503 ??
一般に末尾再帰の形になっていたほうがlazy evaluationと相性よくないか?
うお途中でEnterしてしまったorz
//C
struct Hoge {
DWORD a;
DWORD b;
WORD c[16];
};
Hoge hoge;
fread( &hoge, 1, sizeof(hoge), file );
もしくは
fread( &hoge.a, 1, sizeof(DWORD), file );
fread( &hoge.b, 1, sizeof(DWORD), file );
fread( &hoge.c, 16, sizeof(WORD), file );
//Haskell
data Hoge = Hoge Word32 Word32 [Word16];
parseHoge :: [Word8] -> Hoge
parseHoge = ???
Cの後者の書き方のような場合、fileの中で状態を持ってるから上手くいくんだろうけど、
そういう書き方に相当するのをHaskellでやるならモナド使えってことなのかな
>>507 俺なら面倒だからパターンマッチでやっちまいそうだw
509 :
473:2009/05/22(金) 08:44:48
>>509 末尾再帰の最適化はされてるよ
その例でスタックが溢れるのは別の問題
もし末尾再帰の最適化がなされないなら、$!を使った例でもスタックが溢れるはず
511 :
473:2009/05/22(金) 11:19:42
「末尾再帰最適化されない」というのは誤解を招く表現だったかな。
表面上は末尾再帰最適化手続きによって関数呼び出しが平坦化されても、再帰の際の引数の
変形がlazinessによって結局スタックに積まれてしまい本質的な計算としては最適化されて
いない、ということです。
>>496 ってわざとわかりにくくしてるの?
それともHaskell に慣れるとこんな感じのソースの方がわかりやすいの?
↓こっちの方がよっぽどわかりやすいと思うのは私が初心者だから?
main = interact $ unlines . map f. lines
f:: String -> String
f(' ':xs) = " " ++ (f xs)
f s = s
513 :
512:2009/05/22(金) 13:53:07
ああ、 がスペースになっちゃった。
こう↓ね
f(' ':xs) = " " ++ (f xs)
514 :
512:2009/05/22(金) 15:26:12
補足
「わざとわかりにくくしてるの?」の意図は、たとえば、
A.わかりにくいけど、いろいろなテクニックを披露するためにあえてそうした
B.わかりにくいけど、処理の効率化を考えてあえてそうした
などの場合です。
>>512 それじゃ先頭のスペースしか変換されないよ
>>511 それこそlazinessのおかげで複雑な式が残らずに済むのだが?
>>512 確かにそっちの方が単純で読みやすい気がする
でもまあ好みじゃね?俺はできれば再帰を使いたくない
>>496は、お題を読んで最初に思いついた通りに書いただけ
>>512の書き方には思い至らなかった
>>516 おぬし・・これがスタックオーバーフローの話だったことを忘れてはおるまいな?
最近関数型言語を勉強している者ですが、
パターンマッチとif文、case文の使い分けがよくわかりません。
基本的にif文で書ける者は全部パターンマッチで書ける気がします、
どう使い分けしたらいいですか?
ifを使った方が書きやすい/読みやすいと思ったときに使えばいい
所詮構文糖
>>519 こうしろと言うことはないし、どういう書き方をしても恥ずかしくない。
ただ、なるべく短く書くのがカッコイイ、再帰を使うのはダサイ、ポイントフリースタイルだとカッコイイという風潮はあるかもね。
>なるべく短く書くのがカッコイイ、再帰を使うのはダサイ、ポイントフリースタイルだとカッコイイという風潮はあるかもね。
こういう人が「Haskellは直感的に書けるから!!!」
とか言いながら全く直感的じゃないコードを量産してるんだろうなwwwww
>>523 関数の中身を理解する目的なら、型宣言と自然言語のコメントさえあれば短いコードは非常に読みやすいと思うんだけどね。
一時的に使う変数が多いとごちゃごちゃして見にくい。
>>525 もちろん短いほうが読み易いことは多いが、
普通なら途中に意味のある変数を導入しつつ数行にわたって書くところを
あえて1行でワンライナー的に書いたりするテクニックが可読性を上げるとは到底思えないなー。
むろん短いことが正義なのでコメントとか型宣言とかは一切ないよww。
再帰は関数型では基礎だと思ってたが違うのか…
マ採用試験の基本だな
素人style >341
真のHaskeller >344
ということだな
>>527 Haskellにはfoldlとかmapとかiterateとかいろいろ関数が用意されているでしょ?
わざわざ再帰で終了条件を場合分けをしなくても良いようにそういう関数を駆使すれば良いんだよ。
また、「終了させなくても良い」場合もあるんだよ。
Haskellは遅延評価だから。
>>527 再帰が基本ってのはそうだけど、
表記の上では直接的に再帰で書くのではなく、
map なり iterate なり fold なりを使えという意味だろ。
Scheme なんかでもそういう風潮はあると思う。
>>529 適度な粒度に関数を分けることも重要。
極端なことは駄目。
あまり注目されないけどfixとかapも意外と便利な関数だぜ
便利だよな…1行で書くのに
<$>とか凄く便利、知らないころは>>=return . fとかアフォなことやってた
Cとかに慣れてる奴はポイントフリーの美しさがわからんようだな
____
/ \ /\ キリッ
. / (ー) (ー)\
/ ⌒(__人__)⌒ \ Cとかに慣れてる奴はポイントフリー
| |r┬-| | の美しさがわからんようだな
\ `ー'´ /
ノ \
/´ ヽ
| l \
ヽ -一''''''"~~``'ー--、 -一'''''''ー-、.
ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒)
短く記号で書けたって
数ヵ月後何書いたか判らなくなるだけだよ
>>538 何ヶ月後どころか、1時間後でも何書いたか忘れるけどなにか?
でも型とコメント読めば解るだろ普通
問題は無理にワンライナーで書いたコードはまともなコメントを残しようがないという件
Haskellをまったく知らない中小企業の社長に
おたくのシステムはこうだと、Haskellのソースを
示して理解を得ることだって可能でしょ。
そういう場合は、どんなコードにするの?
ワンライナー含めて、式がネストしてると中間値が見れないからデバッグ等が面倒
なぜ中小企業限定なの?
liftMってなにが便利なの?
モナドがつくれること。
liftMよりFunctorとかApplicative使った方がよくね?
>>541 Haskellを任意のプログラミング言語に置き替えて考えてみよう。
君が考えていることの荒唐無稽さが理解できると思う。
euclidean x y | y == 0 = x
| otherwise = let (b,q) = divMod x y
in if q == 0 then y else euclidean y q
こういうのをごっちゃごっちゃにならんようにポイントフリーにできないものかね?
なんかfold f . unfold gの形(hylomorphismってやつ?)で表現できそうな気はするんだけども…
安直にlast . unfoldr fでやるとfがMaybe(Maybe a)みたいなものを返す必要がでてきて
あまり綺麗にならんのよ.
`mod`を使って、
パターンマッチ渡しに書き換えて、
そのパターマッチ渡し再帰パターンを担うメタ関数を使う、必要なら新たに定義する。
>>548 Prologでは当たり前にやってるよ。
で、日本に無数にある中小企業の社長の何人がPrologハカーなんだ?
>>549 頭の体操って事でArrowで書いてみた。
import Control.Arrow
euclidean = loop eucA
eucA (xy, f) = (f xy, eucA2 f)
eucA2 f = mergeArr . right (appF f . ifZero . mod_snd) . ifZero . swapArr
swapArr = snd &&& fst
-- mergeArr (Left v) = v
-- mergeArr (Right v) = v
mergeArr = id ||| id
ifZero (0, y) = Left y
ifZero (q, y) = Right (y, q)
-- appF f (Left v) = v
-- appF f (Right v) = f v
appF f = id ||| f
-- mod_snd = \ (x,y) -> (mod x y, y)
mod_snd = uncurry mod &&& snd
>>549 それってこれと同じじゃないの?
euclidean x 0 = x
euclidean x y = euclidean y (mod x y)
>>552 ハカーじゃない普通の人でも読めるって話じゃないの?
って話じゃないの?
>>552 粗利経費構成(SS,_年月,_粗利経費構成) :-
月報(数量計,'0110-0350,自動車用燃料合計',X),
月報(粗利計,'0110-0350,自動車用燃料合計',Y),
月報(粗利計,'0110-8999,総合計',Z),
試算表合計(SS,一般管理費科目,_年月,_一般管理費),
試算表合計(SS,人件費,_年月,_人件費),
試算表合計(SS,売上総利益の部科目,_年月,_売上総利益),
member([SS,[MF]],X),
member([SS,[MF粗利]],Y),
member([SS,[_総合計粗利]],Z)
A は MF粗利 / MF,
_油外 は 四捨五入(_総合計粗利 - MF粗利),
Win は _油外 - _人件費,
<以下略>
石油販売会社の社長さんには、上のコードの意味は理解できるものです。
Prologのプログラミングができる必要はありません。
>>558 >>541 の質問は、
>>529 の分類を読んで書き込みました。
すなわち、Haskellの誰にでも理解できるスタイルは
どんなものになりますか? ということです。
>>559 技術的な話を社長にしても仕方ないぜ
コードの説明に力を入れるよりも、開発者が信用を得られるように努力した方が建設的じゃないかな
>>560 それは論点をすり替えてるな
「Haskellの誰にでも理解できるスタイルは」という問いの答えになってない
プログラムは誰にでも理解できるものではありません。
関数型言語は誰にでも理解できるものではありません。
とは思わない。
社長とかおかしいだろ
それいうなら「そのコードをメンテしたくないと思うかどうか」で言うところ
565 :
543:2009/05/24(日) 23:44:58
>>557 ほー。おもしろい。(煽りじゃないよ)
そういう関係のを仕事でやってた?
haskellは理解するものじゃないんだよ
haskellを理解したと誤解するのが正解
本当に理解したのは別の何か
>>564 システムの発注者と利用者が同一人というケースの代表として、
中小企業の社長としたのだが・・・
>>564 ソースプログラムがどこまでドキュメンテーションの役割を
担えるかという話だろ。
別言語のプログラマがひとつ事例を出してくれたのだから、
だれかHaskellの例を書いてみればいいじゃないか。
>>567 その場合に「発注者=利用者」である中小企業の社長はコードを理解せずに
ただ単に利用者として使うものじゃないか?
>>570 成果主義の給与体系への移行などの場合、業績係数がどうの、特別給を
設定しようと、最期まで細部に注文を出すのは、総務部長ではなく、
社長です。その注文に即、対応して、プログラムを変化させるためには、
プレゼンテーションして、予めソースプログラムを読んでもらう他にない。
数行挿入して、そうすると、この社員の総支給はこうなります、と示します。
こうやって試行錯誤しながら、その場でシステムをまとめるのですが、
プログラム言語なんて解らなくても、本当に求めている人には何をやって
いるのか、書いてあるのか、解るのです。
>>557 それ、Prologつーより、識別子名にマルチバイトが使える手続き型言語使うのと同じじゃんw
>>572 そうですよ。COBOL/JAVAと似ているでしょ。
そんなこと関係ないです。
574 :
543:2009/05/27(水) 20:06:58
>>567 最初からそう書いてくれないと分かんないよw
なぜ社長??って理解できなかったぞ
GHCのCore言語 (コンパイル中に使う中間表現) のパーサを書いています。
GHCの実行時に「-fext-core」を付け、書き出されたコードを読むと
「base:GHC.Prim.sym」や「base:GHC.Prim.trans」が登場するのですが、
これらが何なのかご存知の方はいませんか?
GHCの資料を見ても載っていなくて難儀しています。
577 :
575:2009/06/01(月) 23:14:25
「An External Representation for the GHC Core Language
(For GHC 6.10) 」に登場するキーワードの
「%sym」と「%trans」が怪しいと思い、
それぞれ検索置換してみたら、とりあえずパースできました。
ひょっとすると、コンパイラに組み込みの何かから
言語に組み込みのキーワードに変更されたのかもしれません。
意味的にも正しいのかはまだ未確認ですが、
とりあえず全体をパースできるようになってから詳しく見てみます。
578 :
575:2009/06/01(月) 23:18:10
>>576 おおお、
>>577で書いた仕様書には、
「%sym」の右に「transitive coercion」、
「%trans」の右に「symmetric coercion」と書いてありました。
>>576の解説にも同じようなことが書かれているので、
まさしくこれのようですね。
感謝です。
579 :
575:2009/06/01(月) 23:19:11
>>578は、
「%sym」の右に「symmetric coercion」
「%trans」の右に「transitive coercion」
の間違いでした。
何度も済みませんです。
580 :
デフォルトの名無しさん:2009/06/04(木) 11:55:33
フィボナッチ数列を生成する
let fibs = 1:1:2:[x+y | (x,y)<-zip fibs (tail fibs)]
が高速な理由がよくわかりません
fib 1 = 1
fib 2 = 2
fib n = fib(n-1)+fib(n-2)
よりも断然高速な理由はなんでしょう?
結局は一つ数を増すために
zip [1,2,3,5,8,13] [2,3,5,8,13]
[(1,2),(2,3),(3,5),(5,8),(8,13)]
のような計算を毎回やっているって事ですよね。
(8+13)以外はすべて無駄のように思います。
最外簡略とグラフ簡略だから結局は速いのか?
でもfib n = fib(n-1)+fib(n-2)
の圧倒的な遅さは理解できない。。。
zipが行なわれるのは一回だけです。
582 :
580:2009/06/04(木) 14:31:35
>>581 がんばって考えて見た。次の理解であってる?
take 10 fibsとやった時に
fibs = [1:2:a1:a2:..:a7:a8]
tail fibs = [2:a1:a2:..:a7:a8]
そんでこれらのzipは
[(1,2),(2,a1),..,(a7,a8)]
なので
fibs = 1:2:[3,(2+a1),..,(a7+a8)]
っという事になるわけね。
ここでa1が3と評価できて、
次にa2が2+a1=5と評価され、
次にa3がa1+a2=3+5=8と評価され。。。
最後にa7+a8が評価される。
これができるのも最外簡略のおかげ?
ちょwwwこんなのどうやって思い付くの?lol
だいたいあってる。fibsの長さは確定しなくて必要に応じて伸びる。
というか最後にまだ計算されていないかたまりがくっ付いていて必要になるたび計算されて伸びる。
>>2のThe Haskell School of Expressionにくわしく解説されてたような
>>582 等差数列s: S0 = X; S1 = Y; Sn = f(Sn-1, Sn-2) は
s = X:Y:[f(x, y) | (x, y) <- zip s (tail s)]
n-Zがあれば、Zの分:とtailを増やせばいい。
三項に跨がればzip3を使う。
漸化式から導いた数列の筆算を考えると良く分かる。
昔、現在の場所以前の全ての項を使って計算する
x[n] = f(x[0],x[1],...,x[n-1])
という数列を作ろうとし、
x = [f xs | xs <- inits x]
と書いてうまくいかなかった。
原因は標準ライブラリのinitsの実装が不適切で、
head (inits undefined) == []
とならないことだった。
inits' xs = []:if null xs then [] else (map (head xs:).inits.tail $ xs)
と定義しなおしてやれば意図通り計算できた。
undefinedに対する挙動以外は修正前と同じ。
>>505 亀だがやってみた
Offってやつがそれ
import Foreign
import System.IO
import Control.Monad.State
main :: IO ()
main = do
writeHoge file hoge
hoge' <- readHoge file
print $ hoge == hoge'
where
file = "hoge.txt"
hoge = Hoge 3 5 [1,3..32]
-- 書き
writeHoge :: FilePath -> Hoge -> IO ()
writeHoge file hoge = do
withBinaryFile file WriteMode $ \h -> do
with hoge $ \p -> do
hPutBuf h p $ sizeOf hoge
-- 読み
readHoge :: FilePath -> IO Hoge
readHoge file = do
withBinaryFile file ReadMode $ \h -> do
alloca $ \p -> do
hGetBuf h p $ sizeOf (undefined :: Hoge)
peek p
{-
>>588のつづき
-}
--
>>507の
data Hoge = Hoge Word32 Word32 [Word16] deriving (Show, Eq)
-- 読み書きに使うクラス
-- Word系もStorableを実装してるのでそのまま使える
instance Storable Hoge where
sizeOf _ = dword * 2 + word * 16
where
dword = sizeOf (undefined :: Word32)
word = sizeOf (undefined :: Word16)
alignment _ = 8
peek p = runOff $ do
a <- peekOff p
b <- peekOff p
c <- replicateM 16 $ peekOff p
return $ Hoge a b c
poke p (Hoge a b c) = runOff $ do
pokeOff p a
pokeOff p b
mapM_ (pokeOff p) (take 16 c)
{-
>>589のつづき
下の代わりに
type Off a = StateT (Ptr Hoge, Int) IO a
としてちょっと書き換えると上のpが省ける
-}
-- その読み込みモナド
-- オフセットをIntで覚える
type Off a = StateT Int IO a
-- OffをIOでやる
runOff :: Off a -> IO a
runOff m = evalStateT m 0
-- フィールド取り出し
peekOff :: (Storable a, Storable b) => Ptr a -> Off b
peekOff p = do
offset <- get
e <- liftIO $ peekByteOff p offset
put $ offset + sizeOf e
return e
-- フィールド書き込み
pokeOff :: (Storable a, Storable b) => Ptr a -> b -> Off ()
pokeOff p a = do
offset <- get
liftIO $ pokeByteOff p offset a
put $ offset + sizeOf a
質問です。
mapM print [1,2,3]
を実行すると
1
2
3
[(),(),()]
と表示されるのですが、なぜ最後に[(),(),()]が表示されてしまうのでしょうか?
質問です。
[[1],[0..],[],[2,3],[4]]
というリストから要素数が1のリストだけをフィルタするにはどうすればいいですか?
Emacsでghciを起動したとき(haskell-mode からcomintでも、eshellから起動でも)
1~2回何か評価しただけで"Leaving GHCi"とだけ出て勝手に終わるようになってしまった。
何があかんのやろ。
>>592 extractSingleton lst = filter lenChecker lst
where lenChecker [_] = True
lenChecker _ = False
>>593 解答ありがとうございます。
しかし、私が求めている答えとは違うようです。
今回は要素数1でしたが、要素数100のリストだけをフィルタしたい場合はどうすればいいのでしょうか?
595 :
593:2009/06/06(土) 05:29:31
ヾ('A`)/ ズコー
\(.\ ノ
、ハ,,、  ̄
 ̄´´
当方人様の考えを読む能力は持ち合わせていないので、どう違うか書いてくれないことには
にゃんともしがたいですね。
>>593のコードがどのように働くのか、調べてみましたか?
無限長のリストを入力として許容したければlength関数が使えないので
checkLen 0 [] = True
checkLen 0 _ = False
checkLen n [] = False
checkLen n (first:rest) = checkLen (n-1) rest
のように書くしかないのではないかと思う。
>>591 mapM print [1,2,3]自体に[(),(),()]を表示する機能がある訳じゃないので、どうやって実行したかによる
たとえばGHCi上で入力したなら、GHCiのお節介でIO動作の結果が表示される(たとえばGHCi上でgetLineと打ってみれば分かりやすい)
>>594 filter ((==replicate 100 ()) . map (const ()))) list
>>593のlenCheckerを使って
filter (lenChecker . drop 99) list
でもいいな
onlisp読み終わったぐらいなんですが
haskellの勉強するならどの本がお勧めですか
f :: WriterT [String] IO a
comb = do a <- f ; b <- f ; c <- f ; return (g a b c)
bar = do (_, log) <- runWriterT comb ; mapM_ h log
この場合、hがlogの先頭だけしか必要としない場合でも、
f内で行われるIOの動作は3回分きっちり実行されますよね。
これをfが評価される度にhを実行するようにしたいんですが、どうすればいいんでしょうか?
例えばf内でgetLineを使ってるようなとき、
barで入力される度にhがf内のtellで追加された分のログに対して実行されるような動作です
601 :
600:2009/06/10(水) 16:27:16
askUser :: WriterT [String] IO String
askUser = do s <- liftIO $ getLine
tell $ [(printf "input: %s" s)]
liftIO $ putStrLn "accepted"
return s
foo = do a <- askUser
b <- askUser
c <- askUser
return $ a++b++c
baz = do (res,log) <- runWriterT foo
mapM_ putStrLn log
putStrLn res
というコードでfoo bar bazと入力したときに
foo
accepted
input: foo
bar
accepted
input: bar
baz
accepted
input: baz
foobarbaz
となって欲しいという事ですs
602 :
デフォルトの名無しさん:2009/06/10(水) 20:17:38
GHCでのコンパイルがうまくいかないので、相談させてください。
コンパイルしようとすると、
「C:\DOCUME~1\(文字化け。おそらくユーザ名?)\LOCALS~1\
Temp\/ghcXXXX_0/ghcXXXX_0.s:
openFile: does not exist (No such file or directory)
というエラーが出て、全く前に進めないのですが、どうすればいいのでしょうか?
(XXXXは4桁の数字で、コンパイルを試みるたびに別の数字に変わります)
コード内容は、以下のような簡単なものです。
main :: IO ()
main = putStr "Hello, world!"
使用OSは、Windows XP Home Editionです。
>>602 たぶんテンポラリディレクトリにマルチバイト文字が含まれてるとコンパイルに失敗するバグがある
TMPDIR環境変数を設定するか、-tmpdirを毎回渡すかして、日本語の含まれないパスをテンポラリディレクトリに指定してみたらどう?
604 :
602:2009/06/10(水) 21:23:11
>>603 TMPDIR環境変数を設定したらコンパイル通りました!どうもありがとうございました。
なるほど、海外産だから2バイト文字に対応してないんですね。
日本語文字が文字化けしている点で気づくべきでした。
海外産……その一言ですべてが許される魔法の言葉
>>600 何をしたいのかはっきりは分からないけど、多分WriterT [String] IOを使う場面じゃないな
[String]には「必要に応じてIOを行う」みたいな機能はないので、
その機能を持った専用のデータ型を用意する必要があるはず
たとえば
newtype Log = Log (IO (Maybe (String, Log)))
みたいなのとか
今日、仕事帰りの電車の中で「圏論の基礎」を読んでる青年を見かけた。
思わず声をかけそうになってしまった。
「やらないか」
圏論の基礎読んだけどいまいちよくわからなかった
ハッテン場の有り様をHaskellで書けないものか。
Haskellは純粋なので書けません。
うまい!w
確かに、うまい (w
UHCはJHCと同じGrin言語を内部表現に使っているね。
LHCはJHCのコードを使っていた (今は残っていない) というし、
Grin言語は最適化に向いているんだろうね。
メジャーなGHCを含めてパフォーマンスを比較した人とか、いるのかな?
コードフォマッタ機能が欲しいのですが
最近いいIDEでましたか?
漢なら自分でYiをハックしる!女でも。
>>616 あんたみたいなド変態じゃないから
できねーよw
いちいちスペースとかでエラーでるのなんとかしてくれよw
マジレスすればEmacsのhaskell-modeでいいんでねいの?
>>593の問題はhaskell-mode-hookに (setq process-connection-type nil) 追加で自決しました☆
コードをフォーマットするだけなら、これをVimでも何でも
import Language.Haskell.Parser
import Language.Haskell.Pretty
main = do
result <- fmap parseModule getContents
case result of
ParseOk r -> do
putStrLn $ prettyPrint $ r
_ -> print result
>>609 Robert Goldblatt のtopoiを読んでみるといいのでは、今は廉価版などがでているから。
それはハッテン的な内容の本ですか?
Curryスレってないの?
F a の a は対象。
627 :
575:2009/06/19(金) 14:20:40
GHC6.8.3でコンパイルできて6.10.xではできないプログラムを
Javaに移植することになった。
GHC6.8.3が「-fext-core」で書き出す「.hcr」ファイルを
だいたいJavaに変換するトランスレータを書いているのだけど、
もう完成間近になって、「type Index = Int」とか書いた場合に
「.hcr」ファイルには書き出されないことを発見。
他にも「newtype」で元の型が書いてなかったり。
これってバグだよね??
Haskell自体の話では無いけど、有名だったりしますか??
628 :
627:2009/06/20(土) 12:31:18
629 :
627:2009/06/20(土) 12:33:13
間違って送信してしまいました。
「graph.hs」では「type Tag = Int」と書いているんですが、
「graph.hcr」の時点でTagの定義についての情報は消えてしまうんですよね。
バグというよりは仕様なのかな?
>>629 GHC 6.10.1のリリースノートに、
> External core (output only) is working again.
とあることだし、6.8系列でまともに動かないことは知られてたんじゃね?
631 :
629:2009/06/20(土) 14:46:15
>>630 おお、やはりそういう話がありましたか。
パーサを書いていて、仕様書通りで無い部分が
何箇所かあったのでおかしいとは思っていたのですが。
情報ありがとうございました。
centosでghcをパッケージ化してるところはないでしょうか
darcsをコンパイルしたいのです
___ つ
,. ‐¬'´.:.:.:.::`:ー- 、 つ
/.:.:.:.:.::;.:.:.:.:.:.:.:.:.:.:.:.:.:.::丶、
/.:.:.::,.::/:/7: :..:.: .::i.::、.::、:、.:.:.:ヾ:、
/.:/ .: / / 1 | .: .: .: .:| : ト .:i.::ヽ.:.:.:ヽ:、
/.:/.:.::/.:/:/ !.:|.: .: .: .: !: :j i.::|.:.::l .: .: l.::i
. ,'.:/!.:.:_レ'千⌒ヘ.:.:.:.:.:jrァ¬ャ:、」: .:.:.::! :l
,.:/ |.:.:.:|! ,二、ヾ、.:.::/レ' _, 」/ i:| .:.:.:.:|.::|
!′|.:.:i:|.f' 匕ハヽ ∨/ 1J`ト、.l:!.:.:.:.::j.::l
|.:.:|:! じ リ lぃリ !リ.:.:.:.:,'.:.:!
l.:.:|:l "" 丶 ` ´""/.:.:.:.:ハ.:,'
'、:トヾ、 ┌──-ュ /:;ィ.::/ 〃
ヾ\ ゝ ノ /イ:/イ:i
「`¨'¬===┴─────‐--イ不1_ト、|__
| 知らないが |
| |
レ ¬ お前の態度が r─ 、|
r'′-┴、 i⌒ヽ \
i´ -イ 気に入った! `ト、 \ ヽ
634 :
629:2009/06/20(土) 19:45:04
636 :
635:2009/06/23(火) 19:26:25
Cygwin上で試してみたらそんなコマンドが無いと言われしまった・・
もうちょっとやってだめならviスレに行ってみる
637 :
635:2009/06/23(火) 20:04:03
vim-rubyをいれたら使えるようになった。連投スレ汚しすまん。
mtlについて初心者向けに説明した資料ってありますでしょうか。断片的に
色々見てはいますけど、いまいちスッキリ理解ができません。
(.) :: a -> (a -> b) -> b
(.) = flip ($)
"Hello, World".putStrLn
>>639 強いて言うならAll About Monadぐらいか…
ハスケル速くなった?小食になった?
どっちもまだ
readsの戻り値はなぜ配列なのでしょう?
何か区切り文字があるのでしょうか?
カンマで句切ったら別々にパースするのかと思ったら違いました…
Prelude> (reads "1,2")::[(Int,String)]
予想→[(1,""),(2,"")]
結果→[(1,",2")]
読めなかったら[]を返す
複数の読み方があったらそれらを全部返す
しかし、標準のインスタンスのreadsで複数要素が返ることってない気がする
それから、配列じゃなくてリストな
645 :
643:2009/07/10(金) 12:25:18
>>644 なるほど、Maybe の代用にもなるって事ですね
ありがとうございました
以下の様な関数は、標準であるでしょうか?
eachParam::(a->b)->(b->b->c)->a->a->c
eachParam f1 f2 a b =f2 (f1 a) (f1 b)
fst3 (a,_,_) = a
snd3 (_,b,_) = b
thd3 (_,_,c) = c
ないとすれば、関数名は妥当でしょうか?
こういう名前の方が良いというのがあれば教えて下さい。
Haskellでは3つ以上のタプルの扱いは面倒くさいから(a,(b,c))みたいにすると扱いが楽だと思う。
>>646 前半は Data.Function.on
後半は知らない
649 :
646:2009/07/12(日) 04:03:36
>>647 なるほど、それも一つの手ですね。
>>648 ありがとうございます。
やっぱり、あるんですね。
3つ組タプルの取り出しもありそうなんだけどなあ…。
zip3とかはあるのに、なんでだろう…。
圏論とHaskellを勉強しようと思うのですが、今突っ込んでも理解できるとは思えません。
準備運動としては何がオススメでしょうか。。。
とりあえずhaskellだけ勉強して、圏論が必要かどうかはそれから考えるというのはどう。
652 :
650:2009/07/15(水) 22:47:31
>>651 ありがとうございます。
圏論無しでもHaskellって理解できるんですね。なるほどです。
Haskellの入門書でオススメはありますか。
たかが一プログラミング言語だよ、構えるなよ、PHPぐらいの気持ちで行こうぜ
654 :
650:2009/07/15(水) 23:27:10
>>653 どうもです。
いやいや、、、PHPちょこっといじったことありますが、あれ、結構簡単ですよね、たぶん。
Haskellはhaskell.orgを覗いてみたんですが、何か異世界に入ったようにさっぱりわかりません。
日本語の入門書といえば
>>2 の
・入門Haskell
・ふつうのHaskellプログラミング
656 :
650:2009/07/15(水) 23:46:50
>>655 ありがとうございます。
調べてみました。ふつうのHaskellプログラミングの方が評判がいいみたいですね。
英語も多少読めるのですが、洋書だと何がオススメでしょう。
Graham Hutton - Programming in Haskellが評判良いようです、とても。
658 :
650:2009/07/16(木) 01:01:46
>>657 ありがとうございます。
調べました。Mewのかずさんが絶賛してますね。。。
ふつうのHaskellプログラミングとProgramming in Haskellのどちらかに
しようと思います。
みなさん、ありがとうございました。
schoolもいいぜ。
>>655のは取っつきやすさのみが取り柄。
>>655 日本語で Haskell 関連の書籍っていうとその2冊だけだよね?
Real World Haskell の日本語訳のはなしが以前にあったと思うんだけど、
その計画って今はどうなんてんだろ。
haskell-ja のログ見てみるといいことがあるかも
Haskellの本なんか読んだこともないよ。
webで十分だろ。
haskell の数値型について、解説してある所は、ありませんでしょうか?
realfrac や floating、realfloat などの関係が知りたいです。
667 :
663:2009/07/17(金) 16:47:01
>>664-666 ありがとうございます。
後出しですいませんが、その図をみながら考えていました。
知りたかったことは、個々の class が附与する性質です。
細かく分けて階層構造になっているのが、何でかな~と。
特に RealFracとFloatingのあたりの継承関係で分けて行っている部分です。
一応、Haskell 98 Report と、GHC.Float, GHC.Real 辺りを見ながら考えて
よく解らなかったので質問しました。
-- まだ、良くは解っていないのですが、
-- 疑問の発端となったGHCのエラーメッセージが、私の読み取り違いで、
-- 別な部分を直したら、compile 通ったので、motivation は
-- だいぶ落っこちました。
例えば、
RealFracにはDouble, Float, Rationalが入るけどComplex Doubleは入らない
FloatingにはDouble, Float, Complex Doubleが入るけどRationalは入らない
RealFloatにはRationalもComplex Doubleも入らない
cabalコマンドってupgradeやuninstallができなくなってるけど
みんなどうやってパッケージのインストールや更新をしてるの?
鳥のパッケージシステムだと、hackagedbにあるパッケージすべてを
扱えるわけじゃないし
個別にはできますよね。
何か前のバージョンでcabal upgradeしたら整合性がおかしくなって
動かなくなったことがある。色々調べたけど面倒なので入れ直した。
確か今のバージョンでcabal upgradeってやると、そんな感じのメッセージ
でるんじゃなかった?
さっきまさにpackage.confから一行削除してバージョン違いをインストールしなおした
haskellからOpenGL動かしたいんだけどGLUTのインスコの仕方教えてください
sudo emerge freeglut
Redditでこの記事を読んだけど英語力が無さすぎて何が面白いのかよくわからなかった
ヒント ズボンの丈
Haskellコミュニティ
・知的で
・熱狂的で
・職がない
プレゼン中なのになんか寂しそうな顔してるな
>Why Haskell?
自虐的な問いになってしまったようだなw
ワロタ
オライリーのビューティフルコードにハスケルの章あったよね
Haskellが普及しない原因って、単に難しいからなのかな。
それともRailsのようなキラーアプリが無いから?
普及しなくても何の問題もない言語が普及する。
普及しないと何か問題があるような言語は普及しない。
誰特だよって言語が普及するのか
685 :
デフォルトの名無しさん:2009/07/25(土) 22:38:40
>>682 くだらん制約のなかでプログラムを書くのはゲームとしてのおもしろさはあっても
実用にはならないからじゃないか。Haskellはまったく知らなくてちょっとかじって
みようとしたら日本語が出なくて驚いたけどそれ以前に実用になるとは思わないか
ら誰も日本語化しないのだろう。
なんかschemeやprolog,smalltalkをかじったころを思い出した。どれもゲームとし
てのおもしらさはあってもこんなのでプログラムを書きたいとは思わない。
かつてのマイコンと同じようなものかもしれん
スペースリークの問題が解決しない限り
本腰を入れて使いたいと思えない
スペースリークの問題が解決って、何も考えずにコード書いてもスペースリークが発生しないようになるって意味?
それなら永遠に解決されないんじゃね
特に遅延評価に特有の物。だから永久に本腰をいれて(ry
/ \
/ _ノ ヽ、_ \
/ o゚⌒ ⌒゚o \ 今日もまた、コードの間に
| (__人__) | seqをはさむ
\ ` ⌒´ / 仕事が始まるお…
なんか、すげー範囲の狭い仕事だな。
振る人が、大変そう。
昔はPrologプログラムに!を入れる仕事をしてたんだけどね、
もう誰もPrologやってないからこっちに流れてきたんだよ。
そうですか!
>>695 その前はEQUIVALENCEでメモリ効率化ですね!
GHCの一番嫌なところはGHC ver X.Y.Zのライブラリのバイナリがver. X.Y.Z'で使えないこと。
せめてマイナーバージョンが同じならそのまま使えるようにして欲しいものだ。
次に嫌なのはファイルサイズがでかいこと。
gtk2hsのファイナライザの問題は解決したの?
leksahとかが落ちるやつなら五月ぐらいに出たやつで解決してたと思う
701 :
デフォルトの名無しさん:2009/07/28(火) 12:42:41
モナドわかんねーよ!
モナドわかんねーんだよ!
ゆとりでも分かるモナド入門ドキュンメントくれよう…
モナドがわからなくてもIOはできる。
OSのシステムコールとか、プロセッサのIOアーキテクチャがわかってなくても、
C言語から入出力が使えるようなもの。
少し例え話をしよう。
一本の棒があったとする。
武器に使えるし、杖として使うかも、あるいは物干し竿としても使える。
でも、どの用途が棒の本質だろうか?
どの用途も使い道のひとつでなく棒の本質はただ棒であるということにつきる。
つまりはそういうこと。
モナド則を満すものがモナド。
704 :
デフォルトの名無しさん:2009/07/28(火) 13:00:21
続けて
「ゆとり」ってさ、本来の目的で言えば、ゆとりを持った時間で、
好きな事をするってことだろ。
だから、すごい、プログラミングバカとか出てきても良いと思うんだけど。
課外活動を強制とか、結局学校関係で拘束される時間は変わってなかったからな。
そういう意味では不幸な世代だ。
随伴が意味不すぎる
darcsの改造したいのですが、どの本でhaskell勉強するのがお勧めですか
ソース読めばわかるだろ<モナド
モナドいうなクライスリートリプルといえ
>>710の方法で悟った奴っているのか?
超すごいと思うが遠回りな気がするなwww
713 :
アイちゃん:2009/07/28(火) 19:42:23
アハ! メイビとかリストとかモナドだっつっても
実際どういう実装でモナドロウを満たすか確認しないとイケないって事か
リストがモナドだって言われても
あのモナド3ロウからどう実践的活用するのかさっぱり想像つかんかったからな
モナドロウから勝手に使い方まで演繹して使いこなさないといけないと思ってた
>>712 別におかしな方法ではないぜ
モナドを理解する最短の方法だ
ソースを読めば「こんな簡単な事だったのか。数学かんけーねーじゃんwww」
と思うはず。
モナド則がどうのこうのってのは基本的に自分で新しいモナドを作るときだけ気にすればよい。
使うだけならそんなこと覚える必要は全くない。
自分がモナドで気持ち悪いなと思ったのはreturnが他の言語で言うところのreturnと全然違うあたり。
716 :
デフォルトの名無しさん:2009/07/28(火) 20:09:40
ことさらに圏論との関わりを熱く語る人がいるよね
たかがHaskellのモナドごときで大げさに
>>714 >>710はHaskell処理系のソース(ghcとかhugsとか)読むって意味だと思ったわ。
数学関係ないっていうのは全く同意します。
モナドは基本的にライブラリレベルの存在だから、処理系関係なくね?
fundepを応用したキモい型レベルプログラミングもどきを使ったものがあるから
ソース読めばわかるというのは同意できない
720 :
デフォルトの名無しさん:2009/07/28(火) 23:04:45
map 関数などの引数に与える匿名関数の中身全体が
その匿名関数の引数に関する case ~ of しか無い場合、
case ~ of をいちいち書かなくてよい構文糖衣ってありますか?
例えば...
m = map (\x -> case x of
2 -> 20
_ -> x)
[1..9]
こんちは.
『ふつうのHaskellプログラミング』を読んで Haskell に挑戦しています.
今はハノイの塔などのプログラムを練習に書いているレベルなんですが,
円盤を動かした後の塔の状態を逐次表示させようとしたら,関数の引数が
増えたりコードが手続き型っぽくなったりして,嫌なコードになりました.
もう少し Haskell らしいプログラミングをしたいのですが,どんなことに
気をつければよいのかとか,次はこういうことをしてみるといいなどの,
諸先輩方のアドバイスをいただきたいです.お願いします.
>>722 例の場合だとif..then..else があるけど、そういう意味ではないよね…
>>724 そうじゃないです。
すいません、例が悪いと後から気づきました。
しかも、case ~ of じゃなくて if ~ then でした。
簡単に言い直すと、普通の関数なら
f x | x == 2 = ... | x > 2 = ... | otherwize ...
というように書けるけど、匿名関数だと
a = map (\x | x == 2 = ...
なんて書けませんよね。
条件分岐が3つ以上あると、if だと入れ子にしなきゃいけないけど、
| だとそれも見た目綺麗に書けるから、匿名関数でも | を使えないかな、
という質問でした。
>>726 了解しました。
ありがとうございました。
>>723 見てなんとなく作ったハノイの塔をさらしてみる
import Array
hanoi' 0 _ _ _ = id
hanoi' cnt from to mid =
hanoi' (cnt-1) from mid to . ((from,to):) . hanoi' (cnt-1) mid to from
move ary (from,to) = ary // [(from,rest),(to,top:(ary!to))]
where top:rest = ary!from
hanoi cnt = scanl move start $ hanoi' cnt 0 2 1 []
where start = listArray (0,2) [[1..cnt],[],[]]
main = mapM_ (print . elems) $ hanoi 4
>>728 なかなか勉強になります。
配列の使い方がなんとなくわかりました。
windowsでHaskellのコード書くときどんなエディタ使ってますか?
オートインデントとかキーワードの色づけとかインテリセンスみたいな機能の付いたお勧めなエディタって有りませんか?
emacs with haskell-mode
現実問題として emacs 以外の選択肢は無いよなぁ…
Yi がどうかはともかくとしてメモ帳は無いわ…
どんだけマゾなんだよ
↑ん?良く聞こえなかった もっかい言って
メモ帳は無いわ…
どんだけマゾなんだよ
あぁ、ごめん勘違いしてた。
メモ帳じゃなくて TeraPad だった。
さすがに自動インデントの無いメモ帳じゃ効率がた落ちですね。
EclipseFPを試してみたけどHaskell向けのオートインデントってのはないのか。
739 :
デフォルトの名無しさん:2009/08/08(土) 16:29:56
なんでvim使わないの?
俺がvimを使わない理由は、vimの使い方を忘れちゃったからさ
741 :
デフォルトの名無しさん:2009/08/12(水) 21:58:57
最近、D言語みてたらC系列から離れられない奴が癌に思えてきた。
C風の構文でラムダとか汚すぎだろ。
普通に考えたらアホだが、Cから離れたくない奴が多すぎるからDみたいな汚い言語が生まれてくる・
742 :
741:2009/08/12(水) 22:01:59
すまねえ誤爆だ
俺も早くC系列から離れたいけどゲーム屋だから仕方なくC系列
おい、ゲーム屋。
魔女っ子がHaskellという呪文で
魔法の挙動と環境を定義して戦うゲームを作ってくれ。
それなんて現代魔法?
魔法言語リリカル☆LISPってゲームなら既にあるが?
りこさんとすずに匹敵するキャラがhaskellにも必要だ
こよみと美鎖がいるじゃない
Haskellを広めるためにはこういうロビー活動が必要ということだな
Haskell?良い言語だと思うよ?
でもそれが役に立つってんなら
もっと実用アプリが出てきててもいい筈なんだ
reddit haskellの記事全部消化したら買うわ
キタ(´∀`)ーーーーーー???
これ結構前に発売された奴の和訳?
ならネットに訳あるけどな
どう見ても機械翻訳だろ
機械翻訳じゃないだろ
こなれてないだけで
そうか?
余りにも意味不明すぎる日本語だぞ
機会翻訳にいっぴょう
あれはちょっと俺でももっとマシな訳を思い付くというか……
一回機械翻訳して所々手直しした感じかなあ
章によって差が激しい
幸いコード多めだし、原文が併記してあるからギリ読めるw
で、
>>753のはやっぱこれの書籍化なのかね
何か書籍ならではのアドバンテージが無いと買うまでいかないかも
>>761 nobsunさんが関わってるし、それはないだろ……仮にも出版元オライリーだぜ?
ちょっとfailの実用例教えて
サンクス エニウェイ
seq挿入がメンドい
そこは、プロにまかせてみれば?
>>>
>>693 <<<
遅延評価言語でseq使うとか負け組じゃん
*勝ち負けに、こだわらないプログラミング。
*遅延評価言語であえての正格評価がアツい。
デフォルトを正格評価にするオプションありませんか?
非正格だからこそいちいち処理が終わったかどうかとか考えなくて良いのに。
eager haskellを実装して
template haskellのquasi quotationで埋め込む
デフォルトを正格にできたら
使用すると処理が終わらん関数が色んなところで出てきそう
なんか根本的に破綻しそう
776 :
デフォルトの名無しさん:2009/08/22(土) 20:13:36
いちいち不用意に∞リスト使ってないか
ちまちま調べないといけないじゃん
もはやちまちまseqするのと手間の大差はない
不用意に無限リスト使っているかちまちま調べるのが苦痛な場合が思いつかない
例を挙げてください
フローに循環があるかどうかを検出すれば無限かどうかってわかったりしない?
改行はともかく、字下げにまで意味があるのには、いつまでたっても慣れないよ・・・
>>780 それについてはかなり批判が多い仕様だと思うよ。
オフサイドルールで不便だと感じた事はないなぁ
まぁ、ルールとして文法に盛り込む明確な理由も分からんが。
オートインデントがやりづらいのが最大の欠点。
まぁ、最悪{ hoge; fuga; ... }という逃げ道もあるけど。
オフサイドルールについては専用スレがあったような気がするので
そちらにもどうぞ。
オフサイドルールは自分もちょっと不便と感じるかも
サッカーのオフサイドもなんか意味がよくわからんし、よくルール変更あるよね。
パスをつなぐだけでゴールしていいとなると単調になってつまらんということらしい
じゃあパス禁止で
そもそもボールを奪いあう競技なのに相手に触れてはいけないというのが意味不明。
アメフト、ラグビーみたいのがあるべき姿。
つまりオフサイドルールはあまりよろしくない。
スポーツだが戦争みたいに争うのは、教育的にもよくないな。
もっと平和的な精神をいれるべき。
ボールを取るときは、争いではなく話し合いで解決すべき。
そもそも勝敗を付けると負けた方がかわいそう
必ず引き分けになるルールにすべき
そもそも時間の無駄。
競技を禁止すべき。
憲法で規定されている平等を誤解してる奴が多いな。
結果の平等ではなく機会の平等を謳っているだけなんだがな。
>>789 アメフトにもラグビーにもオフサイドはあるわけだが。
>>794 うん、あるよ。でもサッカーみたいに意味不明じゃない。
ラグビーのは「前に投げてパスしちゃいけない」っていうルールから考えると当然のものだし、
アメフトのはボールが動きはじめてから動きなさい、っていう物でしょ?
>>793 じゃあフィールドにボールをたくさん投げ入れて、
どちらのチームにも平均して同程度のチャンスを与えるべき。
1. オフサイドなし
2. ボールのやりとりは話し合い
3. 必ず引き分け
4. プレイヤー全員がマイボールで機会平等
ところでHaskellとラグビーの関係は?
その点に突っ込むのを遅延していたのです
バカばっカリーですね
>>795 > ラグビーのは「前に投げてパスしちゃいけない」っていうルールから考えると当然のものだし、
> アメフトのはボールが動きはじめてから動きなさい、っていう物でしょ?
どっちもハズレ。サッカーのもラグビーのもアメフトのも、
オフサイドラインより前でプレーしてはいけないという原則で一致している。
違うのはオフサイドラインの基準点と、オフサイドの対象となるプレーの基準だけだ。
>>802 どこがハズレなんだ?
別に間違ったこと書いてるか?
まあどちらにしろサッカーではそのオフサイドラインの決め方が意味不明なんだがな。
どうでもいいが、
>>789の意図は、オフサイドうんぬんというより、
ボールを奪いあうのに相手に触れてはいけないという所にあると思うんだが。
サッカーでは接触プレーは認められているよ。知らないの?
ショルダーチャージもスライディングタックルもOKだよ。
バスケと勘違いしてる?
>>803 じゃあ、おまえが理解している「サッカーでのオフサイドライン」の定義をHaskellで記述せよ。
なんでこんなに盛り上がるの…?
もしかして: Unemployed.
逃げたかオフサイド厨www
このスレは堅苦しい話題が多いから、
たまには脱線するのも、まあいいんではないかと。
堅い話題ってどんな話題?
まあ直前に魔法少女ネタで脱線してるわけだが
関数型言語のスレは脱線しやすいのなw
Lispスレも脱線してたぞw
なのは劇場版に期待
>>809が脱線を止める呪文を唱えたおかげでとまったな
今 "Haskell: The Craft of Functional Programming" を読んでいるのですが、
意味が分からないところがあります。
(とりあえず飛ばして先に進んでますが、どうも気になる)
351ページに [Data-directed programming] の例が載っているのですが、
これの何がどう Data-directed programming なのか、誰か説明して頂けないでしょうか。
ここで著者が言ってる Data-directed programming とは、
"計算機プログラムの構造と解釈" で解説されているのと同じものでしょうか。
何がどうっていうか… そのまんまじゃないか
>>820 "The Craft of" の Data-directed の説明と、
"計算機プログラム" の Data-directed の説明が、
全く同じものには見えなかったんです。
前者は単に遅延評価がこんなところで役立つと言っているようにしか読み取れず、
後者は単に関数の型によるディスパッチの方法を述べているようにしか読み取れないんです。
たぶん私が Data-directed の表層しか捕らえられていない為に
これら2つが全く違う事を説明しているように見えるのだと思いますが、
どう同じなのか説明して欲しいんです。
sicpの方はgeneric programmingとかabstract data typeの話題だけど
craft ofの方はデータを加工する関数を組み合わせて目的の値を得るっつう
アプローチと遅延評価が相性いいよとかそういうネタのように思った
確かに全く意味が違ってるな
823 :
デフォルトの名無しさん:2009/08/28(金) 09:05:47
Text.Regex なんですが
メタ文字を文字扱いしたい時どうすれば良いですか?
\. しようとしたらレキシカルエラーです
Haskellの奴は使ったこと無いからよく分からんけど
文字列の中に仕込もうとしてるなら"\\."としないとだめなんじゃないか
有り難う御座いました*´`*
>>826 おお、これは素晴らしい
指示書とかちゃんとその辺がわかってる説明始めて見た
アクションとか「処理系に任せる」という設明は本当に正しいの?
実際の入出力を言語で記述できないのはCだって同じでしょ?
CのIOライブラリも「処理系に任せる」わけで、違いはないと思える…。
829 :
828:2009/08/30(日) 02:55:43
×設明
○説明
はぁ?どこの妄想C言語ですか?
>>828 >>826的に言うと、
Cは「評価」されるとすぐ「実行」されるが、
Haskellはプログラムが終わるか、unsafeIOがくるかでもしないと「実行」されない。
まあ、IOに関していえば、Cであっても、Cの世界では
副作用は起こっていないといえる。
その点ではHaskellとCは同じだろう。
だから826も828も両方正しいだろうね
Cで副作用だといえるのは、
int a=1; //グローバル変数
void function(){
a=2; //副作用
}
のようなソースコードを実行したときだろう
これはさすがに処理系に任せてるわけではないでしょ
>>831 それは遅延評価の話ですよね?
遅延評価がデフォルトのHaskellにおいて
実行順序をコントロールするためにIOモナドが必要なのはわかります。
わからないのは、「処理系に任せるから副作用がない」という説明。
これは本当にIOモナドの説明として正しいのでしょうか?
>>832 IOモナドの説明として正しいのでしょうか?
>>833 Cに副作用がないとは言ってません。
>>831 あっ、すみません。
831さんの説明をよく理解していませんでした。
>Haskellはプログラムが終わるか、unsafeIOがくるかでもしないと「実行」されない。
これ、本当に正しいですか?
まさに、ここが疑問なんです。
Haskellはアクションを組み立てるだけ
→プログラム終了後にアクションが順番に実行される
って事ですよね?本当ですか?
831ではなく、832-833だが
>>834 だから、処理系に任せるという点では同じだといってるじゃん
君のいってることと826はなんら矛盾しない
それから、アクションを組み立てるだけ→いつ実行されるかは終了後であろうが
その場であろうがかまわない
そんなことに意味はないし、処理系依存だろ
現実の世界に副作用が存在するという事実は覆せないから、
出来るのはせいぜい副作用を隠す事だけだ。
でも、副作用は、隠された作用のことで、隠されている事こそが問題だったはずなんだ。
>>832-835 いや、入出力に関してHaskellとCは明確に違う
まず、HaskellにもCにも「式」とか「評価」という言葉があるよな
どちらの言語でも、例えば「円周率の平方根」を表す式は書けるし、
xが正の整数を表す変数だとして、「フィボナッチ数列の第x項」を表す式も書ける
ところが、もう少し詳しく見ると、HaskellとCでは「式」の振る舞いや扱い方が微妙に違う
例えば、「評価されたときに画面にhelloと表示する式」はCでは書けるし、普通のスタイルだけど、
Haskellでは、unsafePerformIOみたいな非常用の装置を使わないと書けないし、実際滅多に書かない
この違いをもって、「Cは入出力に副作用を使うけど、Haskellは使わない」みたいに言う
この違いの影響の一例として、HaskellもCも部分式の評価順を完全には規定しない言語だけど、
Cでは評価順の不定性によって入出力の順番が不定になることがあるのに対し、
Haskellでは普通にIOモナドを使っている限りそういうことはない
> Haskellはアクションを組み立てるだけ
> →プログラム終了後にアクションが順番に実行される
> って事ですよね?本当ですか?
本当だけど、「プログラム終了後」という言葉の意味が直感と違うかもしれない
ここでいう「プログラム終了後」ってのは、「mainが評価された後」ってこと
mainの評価とは、mainをWHNFまで簡約すること。この簡約自体は普通一瞬で終了する
「WHNFまでの簡約」が、普通に言う「実行終了」とは違うってのは次のような例を考えてみると分かる
f :: Int -> Maybe Int
f x = let y = (xを使ったおもしろい計算) in Just y
こうやってfを定義して、「f 5」をWHNFまで簡約しても、おもしろい計算はまだ実行されない
一番外側のJust構築子を発見した時点でWHNFなので、その中身の計算は遅延されるってことね
>>838 現実の世界には作用(つまりアクション)はあっても副作用なんてないよ
副作用とは式を評価する「ついでに」なにかアクションを行うことなんだから、
「式」とか「評価」とかいう概念を持ち込んで初めて副作用という発想が出てくる
Haskellはアクションを「ついで」で実行することをやめて、値として明示的に扱うことにした、それだけ
>>840 不正解。シッタカやめて人の話に真摯に耳を傾ける習慣をつけなさい。
> 副作用なんてないよ
どう不正解なのか分かるように教えてくれ
結局
>>841説明出来ないのか。おまえがシッタカだなw
落ち着け、ひとりで何レスしてんだw
皆がお前みたいに一日中2chに貼り付いて即レスするわけじゃないんだから
待ちゃあいいじゃないか。
ID無い板で何言ってんだか。
ソウダネ、IDナイカラ、ダレガダレダカサッパリワカラナイネ。
落ち着け、ひとりで何レスしてんだw
皆がお前みたいに一日中2chに貼り付いて即レスするわけじゃないんだから
待ちゃあいいじゃないか。
>>839 つまり、「式を評価すると”同時”に、評価以外の何かをする」と
いうのが副作用で、同時でない場合、あるいは、同時か
どうかわからない場合などは副作用と呼ばないということでいいの?
>>837 おお、その上の記事もすばらしい説明だね
最初の1つめの立場をとれば、CのIOにも副作用はないと言えるな
おまえはなにをいってるんだ
式の評価で環境に不可逆の変化が生じるのが副作用
関数型言語において引数・戻り値に現れない作用のことを副作用と呼ぶ
世界を渡せば万事解決
馬鹿が使うHaskellには副作用があるよ。賢い人が使えば副作用はないよ。
add x y = do {
x'<-x;
y'<-y;
print x';
print y';
x''<-x;
print x'';
y''<-y;
print y'';
return (x'+y');
}
main = add (add (return 1) (return 2)) (add (return 4) (return 8))
>>853 一つ目の立場をとれば、CをCの実行プロセスを
式の評価と実行にわけて考えるわけだから、
式の評価までがCだと考えれば、printfやfflushに副作用は
ないと言える
>>851 タイミングはあんまり関係ない
式eが評価されたことによって何か入出力が行われたらそれはeの副作用
式eが評価されて、得られた値に基いて何か入出力が行われるのはeの副作用とは違う
>>857 Cだと式の評価の過程で入出力の実行が起こるから、「式の評価までがC」という言いかたはできないよ
>>858 「評価」という言葉の定義から考えたほうがよさそうだね
>>858 評価の過程で実行が起こっても、その実行をCの外のことだと考えれば
副作用ではなくなるんじゃない?
でも、Cの中と考えるしかないのかもしれないね。
式eが評価されて、得られた値に基いて何か入出力が行われるのを
副作用と呼ぶ立場もあるんじゃないかな。
だって、環境に変化が与えられているから。
>>837の上の記事で言えば2番目の立場
Cの仕様書によれば、実行環境の状態に変化を与えるものを
副作用と呼ぶ
この定義に従うなら、CのIOに副作用はある
Haskellもこれと同じ立場に立つ(実行環境の状態が1つだけ、Haskellの中の
世界にあると考え、それが変化していくととらえ、その変化を副作用と呼ぶ立場)なら、
副作用はあると言える
ただし、
1. 実行環境の状態をHaskellの外のことだと考える立場
2. 実行環境の状態をHaskellの中のことだと考えるけれども、その状態自体を
値だと考える立場
の二つの立場なら、副作用はないといえる
>>860 >式eが評価されて、得られた値に基いて何か入出力が行われるのを
>副作用と呼ぶ立場もあるんじゃないかな。
少なくとも「式eの」副作用ではないよな?
>>861 確かにそう定義されてるけど、実際に規格内で副作用という言葉はもっぱら
式の評価に付随するものとして扱われてるはず
あくまで「式の評価に際して」実行環境の状態に変化を与えることを副作用と呼ぶんだと思う
http://en.wikipedia.org/wiki/Side_effect_(computer_science)
でも混乱を避けることを考えるなら、「Haskellには副作用がない」と言う代わりに
「Haskellではあらゆる式が副作用を持たない」という言い方をした方が良いのかも
>>862 式の評価に付随する場合と、付随しない場合の違いはどうやって区別する?
>>863 式を評価する手順の規則は言語ごとに決まってる訳だけど、その手順に従って式を評価する過程で、
その状態変化を起こすことが規定されている場合に限り、付随すると判断する
でいいかな
>>864 つまり、上のほうで否定した「同時に」ってことだよね
式の評価と同時に何かしても、その「何か」で環境の状態が変化しないならそれは副作用に非ず
>>865 ルールで決まってるかどうかの問題で、タイミングの話はしてないよ
例えば「この式が評価されたら五秒後にメモリを書き換える」みたいなのだって立派な副作用だし、
式を評価しながら同時に環境に何か無関係な状態変化を起こしても、それはその式の副作用じゃない
副作用ってのは環境に変化を与える物だけじゃなくて環境の変化に影響される物もあると思うんだ。
たとえば現在時刻の取得とか。
>>867 ならば、Haskellみたいに、「タイミングはいつかわからないけど、とにかく
この順番に文字を表示しろ」のようなものだって、立派な副作用だろ
>>868 現在時刻の取得自体は副作用じゃないのでは
その例でいけば、現在時刻を変化させてるのが副作用で
参照透明性が満たされないってのも副作用の1つという立場だと
IOモナドでない現在時刻取得関数は参照透明性を満たさないから副作用だよ。
参照の透明性が破られる原因の1つが副作用なのであって、
逆ではないと思うのだが?
>>869 putChar 'a' >> putChar 'b' みたいな式を考えてる?
この式を評価して何年待っても文字は出力されないよ
「aを出力し、次にbを出力する」という手順を表現する単なるデータが返ってくるだけ
>>873 じゃあ、それを評価してみてよw
出力しかしない恣意的な例じゃなくて、出力した結果を入力として受けるような例で。
おまえはいったいなにをいってるんだ
"Haskell: The Craft of Functional Programming" を読んでいて、
また分からないところが出てきました。
空間複雑性(space complexity)の問題です。
確認なんですが、次の2式の空間複雑性は違いますか、同じですか?
(a1) [1,2] ++ [1,2]
(a2) [1,2,3] ++ [1,2]
もうひとつ、次の2式の空間複雑性は違いますか、同じですか?
(b1) [1 .. 5] ++ [1 .. 5]
(b2) [1,2,3,4,5] ++ [1,2,3,4,5]
>>874 >出力しかしない恣意的な例じゃなくて、出力した結果を入力として受けるような例で。
文字列をファイルに書き出して、それを読み込むアクションでいい?
import Control.Exception
action :: IO String
action = do
writeFile "temp.txt" "hogehoge\n" -- temp.txtに出力した結果を…
readFile "temp.txt" -- 入力として受ける
main :: IO ()
main = do
evaluate action -- actionをWHNFまで評価する
putStrLn "done!"
getLine -- すぐに終了しないように入力待ち
return ()
実行してみると分かる通り、temp.txtは生成されない
actionを評価しても、手順を表現する単なるデータが得られるだけで、それが勝手に実行されることはない
それ単なる遅延評価
遅延評価は関係ないよ
評価を強制するためにevaluateを使ってる
temp.txtを読んだ結果を使っていないから、lazynessによって評価されなかった。それだけのはなしだろ。
HaskellのIOはそんな迷惑なlazinessを持たないよ
main :: IO ()
main = do
writeFile "temp.txt" "hogehoge\n" -- temp.txtに文字列を書き込む
readFile "temp.txt" -- temp.txtの内容を読んで捨てる
return ()
これを実行すればちゃんとtemp.txtが作られる
HaskellのIOについて自信満々に語るならせめて基本的な振る舞いくらい知っといてくれ
>>873 何年待っても文字は出力されないってのは嘘だろう
そうじゃなきゃputCharの命令は意味がない
自動的に処理系が実行するという仮定があるじゃないか
ここまで来て誰もhaskell.orgの解説を読めと言わないのはなぜだ?
http://www.haskell.org/haskellwiki/Functional_programming 3.2.4.2 Side effects through monads
Another way of introducing side effects to a pure language is to simulate them
using monads. While the language remains pure and referentially transparent,
monads can provide implicit state by threading it inside them. The compiler
does not even have to 'know' about the imperative features because the
language itself remains pure, however usually the implementations do 'know'
about them due to the efficiency reasons, for instance to provide O(1) mutable
arrays.
Allowing side effects only through monads and keeping the language pure makes
it possible to have lazy evaluation that does not conflict with the effects of
impure code. Even though the expressions are evaluated lazily, some parts of
them are forced by monads to be evaluated in a specific order and the effects
are properly sequenced.
>>878 >>881 つまり、Haskellのevaluateを呼んでもIOは実行されないと
いいたいんだろうが、mainに書けば、実行される
結局、「mainに書けば、式の評価とは別に実行される」という
前提があるわけでしょ?
そういう前提があるにもかかわらず、「付随している」と言わないのは
おかしいでしょ
Cでは、そういう前提のことを付随と言っているわけで
the end
StateMonadのことからやれば、だいぶスッキリすると思うが。> 入出力
直接の答えは載ってないんだけど、考える上で参考になるかもしれない論文
Amr Sabry, What is a Purely Functinonal Language?
http://www.cs.indiana.edu/~sabry/papers/purelyFunctional.ps 「純粋関数型言語」の定義を提案する論文。
「5.2 Effects as Monadic Operations」のところで、モナドにより副作用(状態)を表す言語が(この論文の定義では)「純粋」であることが示されている。
この論文では次のような手順で「純粋である」とは何であるかを探っていく。
1. 明らかに純粋であろうと考えられる言語を用意する
2. 明らかに純粋でないだろうと考えられる言語を用意する
3. 1が「純粋」であり2が「純粋でない」となるような定義を考える
結論から言うと、参照透過性も、observational な等価性も、簡約の合流性も純粋であるということの定義としては不適当で、
代わりに純粋関数型言語の定義として、次の3つの性質による定義を提案している(簡略化したものなので正確な定義は論文を参照のこと)。
1. 純粋型付きλ計算の項を含む。それらの項のセマンティクスは純粋型付きλ計算のセマンティクスと同じである。
2. call-by-value, call-by-name, call-by-nameの3つの評価関数が用意されている。
3. 任意の式Mに対して、3つの評価関数においてMの評価結果が定義されているならば、それらは等しい。
>call-by-value, call-by-name, call-by-nameの3つの評価関数が用意されている。
?
call-by- value, name, "need" の3つだね。
Haskellにcall-by-need以外があるのか?
アクション型の式を「評価」することと、
そこに埋め込まれた処理内容が「実行」されることは違うよってことだよね。
>>877とかは。
「評価=実行」の単純な関係からせっかく逃れたのに「評価」って言うな!みたいな。
実行しなければどうということはない!みたいな。
>>894 そんなのCでも違うよ
評価と実行が何らかの規則で結びついてるから問題なわけで
Haskelldeあってもね
それとこれとは話が違うような
import Control.Exception
main :: IO ()
main = do
evaluate main
return ()
紛らわしいというより、そういう振る舞いをさせる機能を
付随したとか、副作用と呼ばないための定義が
不完全じゃないかといってる
結局、アキレスと亀のパラドックスと同じで、
副作用を発生させる前の時点のみを考察しているから、
副作用は存在しないという結論になっているだけ。
だから、
Allowing side effects only through monads and keeping the language pure makes
it possible to have lazy evaluation that does not conflict with the effects of
impure code.
これが全てでしょ。副作用の有り無しを論じようとするのは筋違い。
このところの流れがさっぱりわからないが
なぜわからないのかがわかったので勉強してくる
すべては一期一会だと言い張る仏教徒みたいなもんだな
面白い言い回し大会終了
>>903は「副作用」という言葉の意味を微妙にずらして説明している部分を取り出しているので
あれだと思うけど、話を見ていると、問題なのは「副作用」の定義だけじゃないと思う。
例えば、I/Oの処理だって「評価」の枠内で実行されてるじゃないか、のような主張。
これがまだ何なのかわからない。
>>907 > 「副作用」という言葉の意味を微妙にずらして
どこがどうずれているんだ?
だって上の方では副作用を含む関数(関数的な手続き)を「impure」と表現しているのに、
「pureな言語に副作用を導入」してなお「言語は依然pure」だ、という言い方は食い違って見えるけど
>>909 副作用をmonadに閉じ込めることで、プログラム全体としてはpurityを損なわないから
pureな言語と呼んでいるんだろう。
突然「monadの中のside effect」という概念が飛び出していると思われ
何を言いたいんだ???
それまでは「式の副作用」しか出てきていないでしょ
>>903の部分は、副作用を「introduce」すると言いながら
その方法として副作用を「simulate」すると(副作用そのものを実現しないように)言ったりして、
厳密さを犠牲にしていることは明らかだと思うよ。
>>916 で、その部分でmonadに言及することの何が問題?
Haskellたん「mainアクション実行するなよ!絶対するなよ!」
式の意味として返却値以外のものがあるとき、それを副作用というんだよ、
副作用のない言語をpureだというんだよ、という流れの中でしか「副作用」が出てきていなかったのに、
(pureな言語において)「副作用をmonadに閉じ込める」というのは、意味を持たないじゃん。
副作用「として実現されていたような種類の動作」を、というならわかるけど。
モナドに閉じ込められている副作用とは、
(言語の実装に必要な) モナドを実行する関数 (:: (Monad m) => m a -> a)
の副作用のことだろうね。
副作用として実装されるだろうけど、言語レベルでは未定義ってこと。
モナドを実行する関数って何?
例えば、対話環境でprint "foo" >> return "bar"と入力すると、"bar"を返す。
つまり、対話環境を実装するにはIO String -> Stringを実装しなきゃいけないんだよ。
アクション × 状態k → 状態k+1
状態 → 返却値
みたいな純粋な関数があればいいのでは。大雑把だけど。
いや、ちょっとアレか。とにかく
・内部状態の変化を純粋な関数で表現できないわけじゃない
・実装時に関数概念を持ち出す必要は特にない
という感じだけど
1> [3] ++ take 3 $ repeat 3
2> [3] ++ $ take 3 $ repeat 3
3> [3] ++ (take 3 $ repeat 3)
リストを結合するとき、3以外エラーになるのは何ででしょう?
1は、ともかく、2がparse error になっちゃうのは、
理由が解りません。
2 でも ++ を前置記法にするとエラーにならずに正しく評価されるな。
>>922 ごめん、入出力の話を
>>923では勝手に内部状態の話にしてしまっていた…。
そりゃそんな簡単じゃないよねw
でも処理系はともかく、対話環境の話はまた別なような…
>>925 もっと簡単な例でもいいのでは。
OK> 1 + 2 + 3
NG> 1 + $ 2 + $ 3
OK> (1 +) $ (2 +) $ 3
OK> (+) 1 $ (+) 2 $ 3
OK> (\x -> 1 + x) $ (\x -> 2 + x) $ 3
優先順位の低い演算子でせき止めても括弧は省略できないよ、という感じ?
$って云うのはSyntax Sugar でもなんでもなくて、単なる中置演算子だから、
++ $ ってやると中置演算子が二つも並んでることになってParseErrorになる。
($) の定義自体は
f $ x = f x
と単に関数適用だけで、あれが上手い具合に働いてるのは infix の指定をよろしくやってるから。
>>903の説明は
>>837の上の記事の第二の立場から見た副作用という言葉を用いて、
第三の立場を説明してるだけじゃん。
× 第二の → ○ 第三の
夏休み終わったのにまだそんな話か
934 :
925:2009/09/01(火) 23:43:28
>>926,927-930
レス、ありがとうございます。
>>930 > $って云うのはSyntax Sugar でもなんでもなくて、単なる中置演算子
Prelude> :type ($)
($) :: (a -> b) -> a -> b
この視点が抜けていました。
すごく良く解りました。
ありがとうございます。
>>928 > もっと簡単な例でもいいのでは。
>>925 の順番は、いつも自分で List を使っているとき、
1 -> エラー -> あっ-> 2 -> エラー -> えっ?あっそーだった -> 3
と、修正していく順番でした。w
>>903はlazinessとimpureが両立するという意味であって、
言語がpureに保たれているなんて一言も言ってないんじゃね?
>>935 > and keeping the language pure
Programming in Haskell の作者のWeb ページに
A Japanese version is currently in preparation.
かいてあるお
>>939 >>876 あほうな疑問かも知れないけど、
規模を示す変数が何もなければ複雑性はO(1)じゃないのかな
>>940 そうでしたか。
では、次の2つでは空間複雑性は違いますか?
(c1) [1, 2, 3, 4, 5, ...... , n-1, n]
(c2) [1 .. n]
私は違うのではないかと考えているのですが。
(分かるとは思いますが、c1 は 1 から n までの整数を直接並べた式です)
(c1) [1, 2, 3, 5, ...... , n-1, n]
(c2) [1 .. 3] + [5 .. n]
すいません、
>>941 のままだと変な質問ですね。
リスト内の全ての要素を評価する関数に引数として c1 や c2 を渡したら、
その関数の評価における空間複雑性は変わるのかという質問です。
で、私は今のところ変わると考えていますが、どうでしょうか。
そう思う理由は長くなるのでレスを分けて書きます。
>>942 はどちらも同じという意味でしょうか。
>>943 と思うわけは以下の通りです。
[Craft of] には 423 ページに次の式が載っており、
[m .. n]
| n>=m = m:[m+1 .. n]
| otherwise = []
[1 .. n] の計算は O(1) だそうです。
なぜなら、この計算は次の様な流れで処理され
[1 .. n]
-> 1 : [1+1 .. n]
-> 1 : [2 .. n]
-> 1 : 2 : [2+1 .. n]
各ステップで [ の前の部分は「出力可能な計算結果の部分」であり、
空間複雑性を測るにはそれ以外の未だ出力できない部分を考える必要がある。
上記の計算ではそのような未出力部分は「サイズが一定」なので O(1) だそうです。
つまり、[1+1 .. n] や [2+1 .. n] の部分は空間複雑性的には同じサイズと言っています。
私はこれを、式を構文の要素に分けた時のその要素数=サイズだと解釈しました。
ならば、
>>941 の c1 を
>>943 のような関数に渡せば、
そのサイズは n に依存するのではないでしょうか。
つまり、c1 は O(n) だと思うのですが、どうでしょうか。
一方 c2 は O(1) だと思います。
>>903はようするに、
「副作用がモナドを通してのみ許され、言語が純粋ならば、
遅延評価と純粋でないコードが衝突しないで共存できる」
と言っている。つまり、
・副作用や、純粋でないコードがどこかに存在する
・しかし、言語は純粋である
といってるように読める
「副作用」とか「純粋」という言葉で「言語」を説明しているのか、
それ以外の何かを説明しているのかがぼやけている人がけっこう多いという印象
IOアクションはパチンコの景品のようなものだと思えばいい。
現金じゃないから賭博じゃないよみたいな。
つまり、言語がpureであるというのは、プログラムが与えられた時に
purely functionalなものとしてWHNFまでreduction出来るということ?
Haskellはmonadを導入することでそれを可能にした。ゆえにpureであると。
>>948 言語がpureであるというのは、モナド絡みで言うなら、式の評価順が変わっても結果は変わらないこと
>>949 「出力」という単語から連想できるものを色々考えてみましたが、
言いたい事がよく分かりませんでした。
いつまでも言葉のドッジボールを続けるより圏論ですよ
>>943-944 入力したデータを保持するだけでO(n)かかるじゃないかってことですよね。
でも元の話は遅延評価のコストの話だと思うので、
値が既に決まっていたら意味を失うような気が。
>>951 出力したらリストも要素もいらなくなるんだから、
作業用の空間はO(1)で押えられるでしょ。
>>954 出力したらリストも要素もいらなくなるんだろうけど、
>>953 が代弁してくれたように、引数で束縛したら保持するので
O(n) 必要なのではと思いました。
> 値が既に決まっていたら
この部分がよく分からないんです。
値が決まる、というのはもうこれ以上簡約できない状態にまで簡約される、
という事ですか。
次のページに下記の式があって
exam4 = list ++ [last list]
where
list = [1 .. n]
これは list が [1 .. n] を hold on to しているので O(n) だそうです。
そういう理由でこれが O(n) なら、この [1 .. n] を [1, 2, 3, .... n] にしても、
おなじ O(n) 必要な気がします。
もしそうなら、[1, 2, 3, .... n] を引数にして関数を呼べば、
その引数がこれを hold on to するので O(n) 必要な気がするのですが、
違うのでしょうか。
つまりですね、何らかの追加的な計算が生じなければ、
「アルゴリズムの」ではなく「ある式の」計算量(複雑性)などと言っても
意味がないのでは、ということです。
>>956 すいません、何らかの追加的な計算とは例えばどういったものでしょうか。
>>943 の「リスト内の全ての要素を評価する関数に引数として c1 や c2 を渡したら」
というのとは追加的な計算とは違うものでしょうか。
>>956 あ、たぶん意味が分かりました。
よく読み返してみたら [craft of] で言っているのは、
ある式の複雑性ではなく、ある計算の複雑性でした。
つまり、「リスト内の全ての要素を評価する関数に引数として c1 や c2 を渡したら」
なんて言っても、その全ての要素を評価する関数の計算方法を決めてやらなければ、
それによって複雑性は如何様にも変わってくるということでしょうか。
exam4で言えば、「list」の具体的な値を求める計算の中でどれだけ同時に記憶領域を使うかという問題だろうと思ったわけです。
それ以外の計算は、exam4のアルゴリズム全体が要求するものですし。
それが遅延評価でしょ。捨ててしまえば0だし。
言い換えると、
同じ式でも、組合せ方によって(次々領域を解放するかによって)遅延評価のコストが違ってくるよ、
という話に見えたという。
>>960 すいません、質問者である私自身がかなり混乱しているので、
どのレスの何に対して言っているのか明確にして頂けるとありがたいです。
それが遅延評価だもんね
>>964 わかりました。
では、次のように定義した foldl に引数として渡した場合はどうでしょうか。
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f st [] = st
foldl f st (x:xs) = foldl f (f st x) xs
(d1) foldl (+) 0 [1 .. n]
(d2) foldl (+) 0 [1, 2, 3, ..... n]
この2つの計算時の空間複雑性はどうなんでしょうか。
どちらも
int v = 0;
for (int i = 1; i <= n; ++i) { v += i; }
return v;
レベルにまで最適化されるのでO(1)
>>967 それなら
>>955 の exam4 も
exam4 = [1 .. n] ++ [last [1 .. n]]
レベルにまで最適化されて O(1) だと思うのですが、
何故こちらは最適化されないのでしょうか。
そういうルールなんでしょうか。
>>968 > exam4 = [1 .. n] ++ [last [1 .. n]]
と
>>955の、
> exam4 = list ++ [last list]
> where
> list = [1 .. n]
の違いを頑張って理解しなよ。
それから、
>>941 > (c1) [1, 2, 3, 4, 5, ...... , n-1, n]
> (c2) [1 .. n]
>
> 私は違うのではないかと考えているのですが。
違うと思う理由を「説明」してみて。
>>969 違いを頑張って理解しようとしている最中なので、しばし待ってください。
> 違うと思う理由を「説明」してみて。
>>944 が理由です。
もう一度いいますと、私は未出力部分はサイズというのは、
式を構文の要素に分けた時のその要素数=サイズだと解釈しました。
それは違うよと言われていないが、この認識が正しいとも確信がないので、
とりあえず未だにこの考えでいます。
なので、c1 は要素数は n に因らず一定だし、
c2 はサイズの増加が n の線形になっているように私には見える。
だから違うと思いました。
すいません。
私は未出力部分はサイズというのは、
==>
私は未出力部分「の」サイズというのは、
exam4は生成後のリストの長さがn + 1だからO(N)じゃね?
仮にコンパイル時に展開されたとしても評価されたときには
リストの長さ分のメモリを食うわけだし
そういう理解じゃ駄目なの?
あと、foldl (+) 0 [1..n]はIntegralだとO(N)ぐらいになるかも…
> > list = [1 .. n]
これは共有される。
> > (c1) [1, 2, 3, 4, 5, ...... , n-1, n]
これは外延的に列挙した記法のつもりらしい。
[1, 2, 3, 4, 5, (略) , n-1, n]
list ++ [last list]
これは、本来単調なループでも書けるくらい簡単な仕事だけど、
こうやって名前をつけて2度書くと一旦全部展開しちゃうんだよ、みたいな例だよね?
ぶっちゃけ考えたことなかったw
勉強になります
いやまてよ…そんなに簡単でもないかも…
やばいProlog脳か…
>>973 ということは、共有されなければ、
where 節で定義しても O(1) で計算できるということでしょうか。
exam5 = list ++ [last [1 .. n]]
where
list = [1 .. 5]
これは O(1) ですか。
すまん、焦ってた。
exam5 = list ++ [last [1 .. n]]
where
list = [1 .. n]
です。
グラフ簡約面白いな
よくよく考えてみたら、exam4 でも O(n) になる理由が分かりません。
(++) と list は次の様な定義ですよね(それぞれ一行にまとめました)。
(++) [] [] = [] ; (++) [] ys = ys ; (++) xs [] = xs ; (++) (x:xs) ys = x : (xs ++ ys)
last [] = error ; last [x] = x ; last (x:xs) = last xs
だとすると、exam4 の評価ステップは次の様になりませんか。
list ++ [last list]
==> (++) list [last list]
==> ++ の定義のどれにマッチするのか調べるために、引数が [] かどうか調べる
==> どちらも [] ではないので最後の定義にマッチする
==> (++) [1 .. n] [last list]
==> (++) 1:[2 .. n] [last list]
==> この時点で x=1、xs=[2 .. n]、ys=[last list] となっているはず
==> 1 : ((++) [2 .. n] [last list])
==> 以下、++ の2つ目の定義にマッチするまで続く
こう考えましたが、すると ++ の2つ目の定義にマッチするまで
list は [1 .. n] をずっと束縛したままなのですが、
それでも、その為に必要なメモリ量は n に依存しない、
つまり [1 .. 3] でも [1 .. 10] でも変わらないような気がするのですが。
どこが間違っているのでしょうか。
>>979 > ==> (++) 1:[2 .. n] [last list]
list変数が押えているから、
このパターンマッチ渡しで受けている1:のコンスセルは捨てられないのだよ。
>>980 何か見えてきたような気がします。
たとえば次の所までステップが進んだとして、
1 : 2 : 3 : 4 : ((++) [5 .. n] [last list])
この段階の list は 1 : 2 : 3 : 4 : [5 .. n] を指して(押さえている)いる
ということでしょうか。
だから、++ の2つ目の定義にマッチするまで、
1 から n までの長いリストがずっと保存されるから O(n)
ということでしょうか。
そうです。
main = print [1 .. 10]
ならコンスセル一個とGCで済みます。(実装によっては二個)
>>982 なるほど、これについてはやっと納得できました。
ただ、
>>967 で O(1) になる理由が曖昧なのではっきりさせたいです。
そもそも「最適化」の仕組みやルールがはっきりしないのですが・・・
foldl の定義が次の様だとして
foldl f st [] = st; foldl f st (x:xs) = foldl f (f st x) xs
次の様に評価のステップが進んだらどちらも O(n) になりませんか?
foldl (+) 0 [1 .. n]
==> foldl (+) 0 1:[2 .. n]
==> foldl (+) ((+) 0 1) [2 .. n]
==> foldl (+) ((+) 0 1) 2:[3 .. n]
==> foldl (+) ((+) ((+) 0 1) 2) [3 .. n]
つまり、((+) 0 1) を評価して 1 にまで簡約しなくても
foldl の2つ目の定義にマッチできるのではないでしょうか。
(+ 演算子の戻り値の型さえ分かれば評価しなくても foldl にマッチする事が分かる)
評価しなくてもマッチするが、それでも効率化のために評価してしまうのが、
最適化なのでしょうか。
それとも最適化は関係なく、((+) 0 1) などは既に出力されていると見なすのでしょうか。
>>967は「最適化」とか適当なこと言っているから気にするな。
>>983 [m..n]というのはenumFromToの構文糖衣と考えれば、これはunfoldrを使って
unfoldr f n
f x = x -> if x <= m then Just x else Nothing
と書けるから
foldl (+) 0 (unfoldr f 0)
= {unfoldr}
foldl (+) 0 (0:unfoldr f 1)
= {foldl}
foldl (+) (0+0) (unfoldr f 1)
= {...}
foldl (+) z (n:[])
= {foldl}
z+n
でfoldlのアキュムレータと(x:未評価のy)
という形のリスト分のメモリしか使用しないのでO(1)
他の例でも[m..n]というものをenumFromToつまりunfoldで置き換えてみよう
あーなんか変だ
f x = if x <= m then Just (x,x+1) else Nothing
[1,3..n]なら
Just (x,x+2)になる
>>985 >>986 [m..n] を unfoldr を使って表現するなら、
f x = if x <= n then Just(x, x+1) else Nothing
unfoldr f m
ですよね(あなたの定義だと m と n が逆なのでは?)。
それは些細な事なのでいいのですが、私が疑問に思っているのは、
==> foldl (+) ((+) 0 0) (unfoldr f 1)
==> foldl (+) ((+) 0 0) (1 : unfoldr f 2)
==> foldl (+) ((+) ((+) 0 0) 1) (unfoldr f 2)
というように + 演算子を引数に適用しないでずっと残していたら、
その分の記憶領域が必要にならないのか、という点です。
で私の考えは、+ 演算子とその引数は評価しなくても foldl にマッチするので、
この時点では評価はされず、つまり + 演算子を引数に適用させずにずっと残ると思うのです。
それは、unfoldr を使おうが、別の方法で [m .. n] を表現しようが同じだと思うのですが。
グラフ簡約だから(+)は一つ記憶しとけばいいのでは?
>>988 (+) の引数(0 や 1 や 2 など)はどれだけ記憶しておけばいいのでしょうか。
全く記憶する必要はないのですか?
zip-archive-0.1.1.3を使っています
このライブラリではData.ByteString.Lazyをソースファイルに使うので
Zipファイルの扱いも定量スペースでできることを期待していたのですが
head $ filesInArchive archiveを評価すると、Zipファイル全部を
メモリに読み込もうとします。
ライブラリのソースを読んでも、どうして定量スペースで処理されないのか
私のレベルでは理解できませんでした。
どなたか御教授ください。
よろしくおねがいします。
おもしろそうなんで調べてみた。
zip-archiveはData.Binary.Getっていうバイナリデータ用のパーサを使ってる。
それで、ZIPファイルを読み込むtoArchiveを単純化すると次のような関数になる。
\入力 -> if パース成功? then 読み込んだデータ else error "エラーメッセージ"
ここで「読み込んだデータ」にアクセスするためには「パース成功?」の部分をTrueかFalseへと完全に評価しなければならない。
この場合「パース成功?」という式は、ZIPファイルが途中で切れてないことなどをチェックする式で、この式を評価するためにはZIPファイルを最後まで読まなければならない。
# ちなみに結果のごく一部にアクセスしたいだけなのに入力を全て読み込まないといけないという問題は多くのパーサにある。
じゃあData.ByteString.Lazyを使う意味はないのかというと、パースした途中でエラーがあったときに残りの部分を読まないとか、ZIPファイルの後に大きなゴミが付いててもその部分は読まないとかの利点はある。
992 :
990:2009/09/06(日) 13:44:49
>>991 非常に分かり易い説明、ありがとうございます。
ファイル毎にrunGetするような実装に書き換えてみたいと思います。
ありがとうございました。
さっきうちのHugsがPreludeの読み込みに失敗したのも、そっち系かな