1 名前:潜伏していた1 mailto:sage [02/02/16 16:55] 何とか生き残れました。 前スレ pc.2ch.net/test/read.cgi/tech/996131288/l50 関連 >>2 以降
707 名前:デフォルトの名無しさん mailto:sage [03/07/15 18:34] >>705 701のイメージはあってるが、 > あと、遅延実行されるのでそう実装しても効率は悪くならないと思う。 遅延実行だからこそそういう式の組み立てと式の保存をやらないといけないわけで、 むしろ遅延評価だからと言ってそういう実装をするととんでもないことになる というべき。 通常の式の評価でも下手に(末尾)再帰すると未評価の式の列が莫大になって すぐオーバーフローする。
708 名前:701 [03/07/15 21:26] 大雑把に読みました。後半のパーサは読み飛ばしましたが… データ型としてのモナドは、要するにC++のクラスtemplate、のようなもの…ですよね? ということは、IO a -> aな関数が記述不可能なのは、言語の外を相手にしたIOモナドに限った制限で 一般的にはそんな制限は無い、で合ってます? 簡単なサンプルコードどこかにないかな…
709 名前:デフォルトの名無しさん mailto:sage [03/07/15 21:44] >>708 リストから成分を抽出できるでしょ。
710 名前:デフォルトの名無しさん mailto:sage [03/07/16 00:34] >>709 ありがとです。 で、>>681 氏と同じ疑問に行き当たるわけですが… リストが状態を持っているとは思えないのですが、なぜモナド? (a, b)とか他の一般の構造化型はモナドじゃ無いですよね。
711 名前:デフォルトの名無しさん mailto:sage [03/07/16 01:00] >>710 リストを丸ごと全部で値と思わずに一部だけ更新したいんじゃない? 一部だけ更新するような操作には普通副作用がある。 …違うかな?
712 名前:デフォルトの名無しさん mailto:sage [03/07/16 01:52] リストは >>= と return がモナド演算の法則を 満たしているからモナドなんじゃないかな (a,b)とか一般の構造型はコンテナの中身の個数が1個ではない定数なのでうまく モナド演算を定義できないような気がする リストモナドの中身は任意個数。IOモナドは1個固定。
713 名前:デフォルトの名無しさん mailto:sage [03/07/16 02:29] 眠れない… えーと、要するに、必然性は無いけど、 モナドということにすると [a] >>= (\e -> return (f e)) みたいな便利機能として使えるので モナドということにしてある、ということですか。 >>711 よく見て無いのですが、ライブラリリファレンスにMutable ArraysとしてIOArrayが書かれてますので、 もしリストモナドで一部の更新が可能なら、こんなもの用意しないと思うので、それは違う気が (我ながら無茶苦茶な論法だ…)
714 名前:デフォルトの名無しさん mailto:sage [03/07/16 02:51] あれもこれも、Haskellの和書が出ないのが悪い。
715 名前:デフォルトの名無しさん mailto:sage=705 [03/07/16 10:48] >>707 すまんが、そういうふうにする以外の方法が自分には想像できない。 doも普通の再帰なので問題はなさそうだが? >>711 リストモナド≒内包表記 副作用を発生できるモナドはIOモナドだけです。 >>710 ListとMaybeだけだね。 試しに、(a, b) でMonadを作ってみたが…きつい。 --- instance Monad ((,) a) where (>>=) (sub, main) f = (sub, main') where (sub', main') = f main return main = (bottom, main) bottom = bottom test = do x <- (("a", 2), 1) y <- return $ x+1 return $ y*2 --- *Main> test (("a",2),4)
716 名前:デフォルトの名無しさん [03/07/16 12:02] だれとはなくに 「型構築子」IO はモナドだけど IO a はモナドじゃないよ。 「型構築子」[] はモナドだけど [a] はモナドじゃないよ。
717 名前:デフォルトの名無しさん mailto:sage 702,706,707,709 [03/07/16 12:17] >>713 haskellのリストやアレイはは一部を変更すると全部コピー。 というのは、そのデータ(リスト等)が他の場所で使われるかもしれないから。 一部を変更したということがそのデータを使うプログラムの他の部分にも わからないといけない。 そのためには、使う部分全部をそのデータの内部状態をあらわすモナドでくるんで おく必要がある。 # 変更し終わったら、それはモナドの外に出してもいい。 >>715 701の件については、誤読していた。それ以降の式、ってのが何を指すのかわからない。 それはともかくとして、 (IO/状態)モナド内の計算の実行は、手続き型と同様にできるとおもうけど。 > 副作用を発生できるモナドはIOモナドだけです。 haskellプログラムがわからみればIOも他のモナドもかわらない。 プログラマから見たときも結局は同じこと。謎の内部状態をもつ モナドを受渡しながら処理を順次実行するわけだから。 内部で定義されたモナドでもそのモナドの性質をみとおさなければ、 副作用と同様でしょう。
718 名前:デフォルトの名無しさん mailto:sage 717 [03/07/16 12:30] 別のいいかたをすれば、711が書いているように、普通一部を変更すると 副作用が出るわけで、関数型言語では一般にはそれができない。 だが、その副作用/状態を追跡するモナド(STArray,IOArray等)を引数と して渡し続けながらの順次計算であれば一部変更もできるわけだ。
719 名前:デフォルトの名無しさん [03/07/16 12:45] だれとはなくに 「データ構築子」はファーストクラスだけど 「型構築子」はファーストクラスじゃないよ。
720 名前:デフォルトの名無しさん [03/07/16 13:13] だれとはなくに モナドは「型構築子」の性質であって、データの性質じゃないよ。
721 名前:デフォルトの名無しさん mailto:sage=699,700,705,715 [03/07/16 15:29] >>717 まず、すまんかった。 確かに中身を見なければ副作用を起こすことは可能だ。そちらの言う通り。 以降の式だが、自分は a >>= (\x -> b) の式に出てくるλのことだと思っている。 そして、715のそういうふうにとは、どでかい合成関数を作ってからそれを実行するということ。 もちろん、遅延実行されるので、少し作ってはそれを実行してというふうになると思っているが。 >(IO/状態)モナド内の計算の実行は、手続き型と同様にできるとおもうけど。 main = sequence_ $ reverse $ [putStr "\n", putStr "a", putStr "b"] こう言うのはどうする…? …特殊すぎるか。他は最適化されててもおかしくないやね。 >>718 少なくともIOArrayはIOモナドの一部であってモナドそのものではないと思うが。 >>719 しかし少なくともカリー化はされている。
722 名前:デフォルトの名無しさん mailto:sage [03/07/16 16:39] >>715 サンプルとして活用させていただきます で、勝手にインデント。 module Main where instance Monad ((,) a) where (>>=) (sub, main) f = (sub, main') where (sub', main') = f main return main = (bottom, main) bottom = bottom test = do x <- (("a", 2), 1) y <- return $ x+1 return $ y*2 >>721 表現が悪くて申し訳ないです。そのつもりでした。do A; B… と書いた時のB以降です。
723 名前:デフォルトの名無しさん [03/07/16 17:37] data Id a = Id a deriving Show instance Monad Id where Id x >>= f = f x return = Id foo :: Int -> Id Int foo arg = do { x <- ID arg ; x <- ID (x * 2) ; x <- ID (x + 1) ; return x } というHaskell のプログラムと、 int foo (int arg) { int x; x = arg; x = x * 2; x = x + 1; return x; } は、そっくり。上は副作用をつかってないですけど、 下は副作用をつかっています。 そんだけ。 int
724 名前:デフォルトの名無しさん [03/07/16 18:28] >>723 ID じゃなくて Id
725 名前:デフォルトの名無しさん [03/07/16 20:17] 突然ながら、FFIを試してみたり… #include "hsFFI.h" #include <stdio.h> void __stdcall print_hex(HsInt a) { printf("%x", a); } foreign import stdcall "print_hex" printHex :: Int -> IO () main :: IO () main = do printHex 1234 >ghc ffi.hs ffi_c.hc -fglasgow-exts Warning: retaining unknown function `_print_hex@4' in output from C compiler 動くんですけど、このWarningが消せない…
726 名前:デフォルトの名無しさん mailto:sage ... 717 718 [03/07/16 22:59] >>720 > 以降の式だが、自分は a >>= (\x -> b) の式に出てくるλのことだと思っている。 > そして、715のそういうふうにとは、どでかい合成関数を作ってからそれを実行するということ。 よくわからない。ダイナミックに関数を作ると? > ... > main = sequence_ $ reverse $ [putStr "\n", putStr "a", putStr "b"] 関数ポインタの配列をつくっておいて並べ替えるのかな。 >>721 > 少なくともIOArrayはIOモナドの一部であってモナドそのものではないと思うが。 確かに、モナドはそれぞれIOとSTだ。 モナドの一部っていうのもよくわからないが… monad-awareという感じか。
727 名前:デフォルトの名無しさん mailto:sage [03/07/16 23:31] >>725 __stdcall -> ccall、ffi_c.hc->ffi_c.c で ghc -ffi ffi.hs ffi_c.c とすると何のWarningもなくコンパイルを通った(Windowsではない)。
728 名前:デフォルトの名無しさん [03/07/17 01:25] 誰か Haskell の和書書いてくれよ。 5000円くらいまでなら買うからさ。 和書ないとやる気が出ねぇし、普及なんて夢のまた夢だよ。
729 名前:デフォルトの名無しさん [03/07/17 02:06] Haskellはドイツ語でクシャミの事
730 名前:デフォルトの名無しさん mailto:sage [03/07/17 04:00] >>727 拡張子を変えたら警告が出なくなりました。 よくよく見てみれば.hcってコンパイラが生成したCソース用の拡張子… どうも、お騒がせしました。
731 名前:デフォルトの名無しさん mailto:sage [03/07/19 19:40] >>729 くしゃみが出るくらいに香辛料の効いたカレーを“Haskell Curry”と云う!?
732 名前:デフォルトの名無しさん mailto:sage=721 [03/07/19 22:54] >>726 >よくわからない。ダイナミックに関数を作ると? その通り。 (.) が関数を合成するのと同じように。 >関数ポインタの配列をつくっておいて並べ替えるのかな。 引数等を保存しておく必要があるので、それをすると、λと変わらないと思う。 >>722 無理しているので、return a >>= k = k a が成り立たなくなってたりしているので注意。 ついでに、前に作ったモナドをどうぞ。 面倒を少し減らす程度のものですが。 --- module Main where --type ReadS a = String -> [(a,String)] newtype ReadR v = ReadR { runr :: ReadS v} instance Monad ReadR where ReadR r >>= fr = ReadR (\str -> [ret| (v,str') <- r str, ret <- fr v `runr` str']) return v = ReadR (\str -> [(v, str)]) rread :: (Read a) => ReadR a rread = ReadR reads rlex :: ReadR String rlex = ReadR lex test :: String -> (Int,String) test str = head test' where test' = do rread `runr` str --- Main> test "125 " (125," ")
733 名前:デフォルトの名無しさん mailto:sage [03/07/21 01:46] Randomを使ったコードを少し書いて見ました。 毎回の let (r2, g2) = random g1 in … 数字は使うたびに増やす…が面倒だったので、 モナドにすれば好きな時に r2 <- nextRandom とか書けるのかなあ、とか思ったり。 (既にあるのかもしれませんが) >>732 うう、ありがとうございます。しかし、私のレベルでは何をやっているのかと用途の両方がわかりません…。
734 名前:デフォルトの名無しさん mailto:sage [03/07/21 01:52] >>732 |無理しているので、return a >>= k = k a が成り立たなくなってたりしているので注意。 モナドの法則を満たさなくてモナドといえるの?
735 名前:デフォルトの名無しさん mailto:sage [03/07/21 02:33] module RandomProgression where import Random data RandomProgression r a = RP (r -> (a, r)) nextRandom :: (RandomGen r, Random a) => RandomProgression r a nextRandom = RP (\r -> random r) instance Monad RandomProgression r a where --(>>=) :: RandomProgression r a -> (a -> RandomProgression r b) -> RandomProgression r b RP x >>= f = RP (\r -> let (a, r') = x r in let RP b = f a in b r') --return :: a -> RandomProgression r a return value = RP (\r -> (value, r)) 書いてみました…instanceでエラーが出ます…わかりません… ↓こんな風に使えたらいいなと思ってる let (answer, g) = (do a <- nextRandom; return (a `mod` 10)) (mkStdGen 100)
736 名前:デフォルトの名無しさん mailto:sage [03/07/21 02:45] 括弧が要るんですね… instance Monad (RandomProgression r) where 実行用に eval :: (RandomGen r) => RandomProgression r a -> r -> (a, r) eval (RP e) r = e r 書き足して RandomProgression> eval((do x <- nextRandom; return (x `mod` 10)) :: RandomProgression StdGen Int) (mkStdGen 10) (7,432453652 1655838864) 動いたー! どうも、スレ汚しごめんなさい
737 名前:デフォルトの名無しさん mailto:sage [03/07/21 02:59] >>733-736 そんなことをする必要はない。 randoms (mkStdGen 1) ::[Int] のようにして無限乱数列が作れるのだから。 Make use of the power of lazy evaluation ! # あとはそれにmapでもなんでもして加工すればいい。
738 名前:デフォルトの名無しさん mailto:sage [03/07/21 15:25] ハクションと似てなくもないような
739 名前:デフォルトの名無しさん mailto:sage [03/07/21 19:05] >>737 なるほど!遅延評価を忘れてました。 しかしそれでも2個の乱数を取ってきたい時は、let (r1:r2:rs') = rs (以降はrs'から取る) みたく 乱数列を意識して渡していかないといけないような。いや、ずっと書きやすいではありますが。
740 名前:デフォルトの名無しさん mailto:sage=732 [03/07/21 20:22] >>734 知らん。気になるのなら、たとえば、こうすればちゃんとモナドになる。 module Main where instance (Num a) => Monad ((,) a) where (>>=) (sub, main) f = (sub+sub', main') where (sub', main') = f main return main = (0, main) >>733 まずちょっと修正...スマソ。 import Monad -- 追加 instance Monad ReadR where ReadR r >>= fr = ReadR (\str -> [ret| (v,str') <- r str, ret <- fr v `runr` str']) return v = ReadR (\str -> [(v, str)]) fail s = mzero -- 以下追加 instance MonadPlus ReadR where mzero = ReadR (\s -> []) mplus (ReadR f) (ReadR g) = ReadR (\s -> f s ++ g s) 用途としては、下のようなコード(やさしいHaskell 8.3節からコピペ)のtuvwxのような変数を書かなくてもよくすること。それだけです。 >readsTree :: (Read a) => ReadS (Tree a) >readsTree s = [(Branch l r, x) | ("<", t) <- lex s, > (l, u) <- readsTree t, > ("|", v) <- lex u, > (r, w) <- readsTree v, > (">", x) <- lex w] > ++ > [(Leaf x, t) | (x, t) <- reads s]
741 名前:デフォルトの名無しさん mailto:sage=740 [03/07/21 20:26] 上のコードのReadR版 >rreadTree :: (Read a) => ReadR (Tree a) >readsTree s = rreadTree `runr` s >rreadTree = do "[" <- rlex > l <- rreadTree > "|" <- rlex > r <- rreadTree > "]" <- rlex > return $ Branch l r > `mplus` > do x <- rread > return $ Leaf x
742 名前:デフォルトの名無しさん mailto:sage [03/07/21 20:38] >>739 なんかまだ手続き型の頭のような気がする:) 関数型だったら結局繰り返しは再帰で書くんだから、 結局こんな感じになると思う。 f 0 result rs = result f n result (r1:r2:rs) = f (n - 1) (g r1 r2 result) rs # f 10 [] randomlist のように使う。 # g で欲しいものを計算。
743 名前:デフォルトの名無しさん mailto:sage [03/07/21 20:39] う、結局が二つも。
744 名前:デフォルトの名無しさん mailto:sage [03/07/22 01:26] >> 740 Num a が気になる
745 名前:デフォルトの名無しさん mailto:sage [03/07/23 22:09] GHCって実はfromIntが無かったりします…? Variable not in scopeと言われるのですが
746 名前:デフォルトの名無しさん mailto:sage=740 [03/07/24 01:42] >744 気にするな。
747 名前:デフォルトの名無しさん [03/07/24 10:52] >>745 fromInteger じゃだめなの? 今のHaskell 98 の Prelude には fromInt は無いのでは。
748 名前:デフォルトの名無しさん mailto:sage [03/07/24 20:52] >>747 いえ、Intからの変換にfromInteger (toInteger n)と書くのが冗長な気がしただけです。
749 名前:デフォルトの名無しさん [03/07/29 00:04] >>748 Enum クラスのメソッドが使えるのでわ。 toEnum :: Int -> a fromEnum :: a -> Int
750 名前:デフォルトの名無しさん mailto:sage [03/08/01 10:11] >>749 FloatやDouble…のつもりでしたが、それらもtoEnumでいけるのですね。 ありがとうございます。そして遅レスごめんなさい
751 名前:デフォルトの名無しさん [03/08/02 01:34] ニセ手続き型?の基本的なもなどはなんとなくわかった(というか「同じやん」ということで) けど、それ以外のモナドがワカンネ。 ライブラリ読んでみたりしたけど激むず。 モナド難しいですね。 ニセ手続き型を理解したあとは、どうしたらよいのでしょうか
752 名前:デフォルトの名無しさん mailto:sage [03/08/02 19:05] GHCのText.Regexで matchRegex (mkRegex "abc") "xabcx" => Just [] matchRegexAll (mkRegex "abc") "xabcx" => Just ("x","abc","x",[]) これってバグ?
753 名前:デフォルトの名無しさん mailto:sage [03/08/02 19:42] あ、二つ目は書き間違い。 matchRegexAll (mkRegex "abc") "xabcx" => Just ("","abc","x",[])
754 名前:デフォルトの名無しさん mailto:sage [03/08/02 19:54] モナドの問題点とかは特に上がってないのですか? 実行効率周りとか。
755 名前:デフォルトの名無しさん mailto:sage [03/08/08 01:02] GHC 6.0.1 Released
756 名前:デフォルトの名無しさん mailto:sage [03/08/08 07:07] >>755 いただきました
757 名前:デフォルトの名無しさん mailto:sage [03/08/11 13:30] 素朴な疑問なのですが Haskell の言語使用はかなり頻繁に変わるものなのでしょうか? 2000年あたりに出版された本で勉強しようかと思っているのですが、それいらい大きく変わったとか、 近いうちに大きく変わるとか、ありますか?
758 名前:デフォルトの名無しさん mailto:sage [03/08/12 00:36] 基本はHaskell98から変わってないんじゃないだろうか。 処理系によっては独自拡張があることも。
759 名前:デフォルトの名無しさん mailto:sage [03/08/12 21:05] >>758 サンクスコ。 言語仕様は大きく変わってないから、そのころの本で勉強しても問題ないということですね。 がんばって勉強してみます。 (関数型言語は使ったことがないから、なじめるかわからないけど)
760 名前:デフォルトの名無しさん mailto:sage [03/08/13 20:49] 確かに言語仕様はほとんど変わっていないが、 ライブラリがかなり違うような気がする。 ライブラリは階層化ライブラリ(Data.Listとか) で決まりでいいのだろうか。 標準ライブラリ以外になると混沌としか言い様がない
761 名前:デフォルトの名無しさん mailto:sage [03/08/13 21:45] Hugsもライブラリを2通り持ってるね。
762 名前:デフォルトの名無しさん mailto:sage [03/08/13 22:52] www.haskell.org/onlinelibrary/ ここにあるのが標準ライブラリーで、足りない部分は、 www.haskell.org/libraries/ から探すとか、自作するということですか? www.haskell.org/ghc/docs/latest/html/libraries.html で、これが HUGS についてくるライブラリー群?
763 名前:デフォルトの名無しさん mailto:sage [03/08/14 00:53] Hugsのライブラリについて書いてあるよ。 cvs.haskell.org/Hugs/pages/hugsman/libs.html GHCは5.04.1=>6.0でライブラリ関係が少し変わっているような気がする。
764 名前:デフォルトの名無しさん mailto:sage [03/08/15 02:04] 前スレは約一年に使い切ったのに、part2 に移行して少し停滞してます。
765 名前:デフォルトの名無しさん mailto:sage [03/08/15 02:29] www.cse.ogi.edu/ 〜hook/cse532f99/haskell1.htm ↑赤黒木の実装に感動。 だれか、コンパクトなdelete実装しれ!
766 名前:山崎 渉 mailto:(^^) [03/08/15 16:09] (⌒V⌒) │ ^ ^ │<これからも僕を応援して下さいね(^^)。 ⊂| |つ (_)(_) 山崎パン
767 名前:デフォルトの名無しさん [03/08/19 11:49] 6.0.1入れたらwxHaskellが使えなくなっちまった
768 名前:デフォルトの名無しさん mailto:age [03/08/19 15:54] win de GUI no hito mada-?