関数型プログラミング言語Haskell Part8
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2007/10/30(火) 20:28:13http://www.haskell.org/
日本語サイト
http://www.sampou.org/cgi-bin/haskell.cgi
http://www.shido.info/hs/
過去ログ
関数型プログラミング言語Haskell
Part1 http://pc.2ch.net/tech/kako/996/996131288.html
Part2 http://pc2.2ch.net/test/read.cgi/tech/1013846140/
Part3 http://pc8.2ch.net/test/read.cgi/tech/1076418993/
Part4 http://pc8.2ch.net/test/read.cgi/tech/1140717775/
Part5 http://pc8.2ch.net/test/read.cgi/tech/1149263630/
Part6 http://pc11.2ch.net/test/read.cgi/tech/1162902266/
Part7 http://pc11.2ch.net/test/read.cgi/tech/1174211797/
・2chの仕様により、行頭の半角スペースは表示されません。
コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
0175デフォルトの名無しさん
2007/11/17(土) 07:11:03型推論。fooの型とbarの型とその式の使われ方が勘案される。
0176デフォルトの名無しさん
2007/11/17(土) 11:11:46それはコンパイル時と実行時のどちらでされるものなんでしょうか?
0177デフォルトの名無しさん
2007/11/17(土) 11:43:58実行時
0178デフォルトの名無しさん
2007/11/17(土) 11:57:24・ただし、型クラスのディスパッチは実行時まで遅延される。
・ただし、どのインスタンスについてのコードを生成すれば良いか静的に決まる場合は、
最適化の一環としてディスパッチを省略する。
こんな感じか。
0179174
2007/11/17(土) 12:49:35なるほど、静的に型をチェックしつつ、動作は動的に決まるんですね。
ところで
数学パズル ものまね鳥をまねる―愉快なパズルと結合子論理の夢の鳥物語
ttp://www.amazon.co.jp/%E6%95%B0%E5%AD%A6%E3%83%91%E3%82%BA%E3%83%AB-%E3%82%82%E3%81%AE%E3%81%BE%E3%81%AD%E9%B3%A5%
E3%82%92%E3%81%BE%E3%81%AD%E3%82%8B%E2%80%95%E6%84%89%E5%BF%AB%E3%81%AA%E3%83%91%E3%82%BA%E3%83%AB%E3%81%A8%E7%B5%
90%E5%90%88%E5%AD%90%E8%AB%96%E7%90%86%E3%81%AE%E5%A4%A2%E3%81%AE%E9%B3%A5%E7%89%A9%E8%AA%9E-%E3%83%AC%E3%82%A4%E3%
83%A2%E3%83%B3%E3%83%89-%E3%82%B9%E3%83%9E%E3%83%AA%E3%83%A4%E3%83%B3/dp/4627019017/ref=sr_1_9?ie=UTF8&s=books&qid=1195271100&sr=1-9
この本を読んだことがある人いますか?関数プログラミングの土台の考え方がわかる本らしいんですが。
0180デフォルトの名無しさん
2007/11/17(土) 13:28:59途中まで読んだだけだけどコンビネータの話。
S,K,I とか。Yコンビネータも出てきたかは覚えてない。
0181デフォルトの名無しさん
2007/11/17(土) 16:07:56a 2 = 2
のような引数によって異なる型の値を返すことはOKなんでしょうか?
0182デフォルトの名無しさん
2007/11/17(土) 16:22:37template haskell
0183デフォルトの名無しさん
2007/11/17(土) 16:25:26ダメ
0184デフォルトの名無しさん
2007/11/17(土) 16:30:24a :: Int -> Either String Int
a 1 = Left "hoge"
a 2 = Right 2
0185182
2007/11/17(土) 16:51:520186デフォルトの名無しさん
2007/11/17(土) 22:16:41今日Haskell始めたばかりのド素人なんだけど、
ones = addlist 1 onesでも、
addlist init xs = init : head xs : tail xs -- [1,1,1,1,1,1,1,1,1,1]
addlist init xs = init : xs -- [1,1,1,1,1,1,1,1,1,1]
addlist init ~(x:xs) = init : x : xs -- [1,1,1,1,1,1,1,1,1,1]
addlist init (x:xs) = init : x : xs -- C stack overflow
ってなる。要するに(x:xs)が含まれる部分が先に解釈されるとマズいってことじゃないかな。
単体でのxsはパターンはパターンでも手続き型言語での仮引数と同じ程度の意味しかもたないパターンだから暗黙的に遅延される。
head xsやtail xsも関数だからxsが未確定なら遅延される。
でも(x:xs)というパターンは未確定でも遅延しないでxとxsを照合しようとする。
結果的にinitに値がセットされる前にx:xsを延々と調べ続ける。それではマズいので、(x:xs)を遅延パターンにする、ってことじゃないかな。
0187デフォルトの名無しさん
2007/11/17(土) 23:24:01明日からHaskell始めるつもりのド素人なんだけど、
関数の仮引数xがconstructor pattern(たとえばy:ys)の場合、
それはcase x of y:ys -> ...という形に変換される。
で、caseの条件式はWHNFまで評価されてしまうので、
遅延させたい時には使えない。
0189163
2007/11/17(土) 23:59:14Haskellの考え方に慣れるまでまだ時間がかかりそうですorz
0190デフォルトの名無しさん
2007/11/18(日) 00:28:05sequence = foldr mcons (return [])
where mcons p q = p >>= \x -> q >>= \y -> return (x:y)
↑のsequenceの定義を見るとfoldrが使われているんですが、それだと
sequence [putStr "foo", putStr "bar"] の場合リストの後ろの方、
つまりputStr "bar"の方が先に評価されるのに、実際には
fooの方が先に出力されてしまいます。どうして後ろからではなく、先頭から
評価されるんでしょうか?
0191デフォルトの名無しさん
2007/11/18(日) 00:55:140192デフォルトの名無しさん
2007/11/18(日) 01:04:47= A `mcons` (B `mcons` (C `mcons` (return [])))
= A >>= (\x -> (B `mcons` (C `mcons` (return []))) >>= \y -> return (x:y))
よってA, B, Cの順にエフェクトが出る。
0193デフォルトの名無しさん
2007/11/18(日) 01:17:35Haskell今日始めた人なんだけど
その最適化の一環としてディスパッチが省略された場合ってのは
C++でいうとtemplateによってコード生成された状態と考えていいんですかね
0194デフォルトの名無しさん
2007/11/18(日) 02:12:23main = putStr "hoge" >>= \x -> putStr "foo" >>= \y -> return y
main = putStr "hoge" >>= \x -> putStr "foo" >>= \y -> return "bar"
↑のように最後にreturnさえすればエラーにならずhogefooと出力されるということは、
IOモナドはMaybeモナドやListモナドと違って、最後に何を返すかではなく、
動作をどういう順に行うのかを決めるための仕組みだと考えればいいんでしょうか?
0195デフォルトの名無しさん
2007/11/18(日) 08:09:29そんな感じ。
>>194
何を返すかによってmainの型が違う。
上の二例ではIO ()で、最後の例だとIO String。
両方コンパイルが通るのは、mainの型はIO αという形なら何でもよく、
生成されたα型の値は無視されることになってるから。
0196デフォルトの名無しさん
2007/11/18(日) 13:45:25実行時にならないとどのインスタンスのコードが実行されるか
静的に決まらない場合ってどんな場合??
0197デフォルトの名無しさん
2007/11/18(日) 13:51:59クラスのインスタンス一般に対して書かれた関数は全部そう。例えば、
double :: (Num a) => a -> a
double x = x + x
こんな関数を定義したら、これをコンパイルする時点ではどの(+)を使うべきか決まらない。
0198193
2007/11/18(日) 13:56:54その関数doubleに対して具体的に値を入れたときに
コード生成される(静的に生成?)んじゃないんですかね?
頭がC++脳なのでtemplateのことばっかり頭に浮かんでしまうんですがね…
0199デフォルトの名無しさん
2007/11/18(日) 14:08:31少なくともGHCやJHCならdoubleが定義されたモジュールをコンパイルする時点でコードを生成する。
そうじゃないと、doubleを使う度に毎回doubleをコンパイルすることになって、
分割コンパイルの恩恵が薄れる。(C++はあえてこれをやってるわけだが)
それから、Haskellの仕様上、完全に静的に済ますわけにはいけない。
newtype P a = P a deriving Show
nq :: (Show a) => Int -> a -> String
nq 0 x = show x
nq n x = nq (n-1) (P x)
こういう関数をtemplate式でコンパイルしようとしたら、無限にnqのインスタンスを生成する必要がある。
あと、実際にはdoubleのような小さい関数はインライン化されるので、ディスパッチが省略される可能性はある。
0201デフォルトの名無しさん
2007/11/18(日) 14:34:20↑がこうなるのはわかるんですが
1:2:3 -> ?
とやった場合はどんなデータができるんでしょうか?
0202186
2007/11/18(日) 14:42:100203デフォルトの名無しさん
2007/11/18(日) 14:43:060204デフォルトの名無しさん
2007/11/18(日) 14:46:12(:) :: a -> [a] -> [a]
0205デフォルトの名無しさん
2007/11/18(日) 14:48:27やってみりゃいいじゃん。それで挙動に疑問があったらここでもう一度聞いてみな。
0206201
2007/11/18(日) 15:25:47なるのにghciで:t 1:2とやると
1:2 :: (Num t, Num [t]) => [t]
というなんだかよくわからないメッセージが出ます。
:tだと型チェックしないのかなと思ったんですが
:t putStr 1
とやると今度はきちんとエラーが出ます。
・1:2 :: (Num t, Num [t]) => [t] は一体どういう意味なのか
・なんで:t 1:2はエラーにならないのに:t putStr 1はエラーになるのか
↑2つになる理由は何故なんでしょうか?
0207デフォルトの名無しさん
2007/11/18(日) 15:43:17GHCは型クラス周辺を微妙に拡張してるからそのせいだろう。
Haskell98では(Num [t])という文脈はありえない。
Hugsで :t 1:2 と入れたらエラーが出たし。
0208デフォルトの名無しさん
2007/11/18(日) 15:44:430209デフォルトの名無しさん
2007/11/18(日) 15:53:43Haskellでは1とか7とかの整数リテラルは(Num a) => aという型を与えられる。
つまりNumのインスタンスなら何にでもなり得る。具体的にはIntでもIntegerでもRationalでもいいし、
未知のユーザー定義型でもいい。
「1:2」という式では、とりあえず「1」の型をtと書くと、整数リテラルだから(Num t)という制約が必要。
(:)の右辺の型は左辺の型のリストだから、「2」の型は[t]。これも整数リテラルだから制約(Num [t])も要る。
式全体の型は右辺と同じで[t]だから、結果として(Num t, Num [t]) => [t]になる。
0210201
2007/11/18(日) 16:16:460211デフォルトの名無しさん
2007/11/18(日) 16:19:47書かれていないとも限らない、ということですか。
0212デフォルトの名無しさん
2007/11/18(日) 16:44:20初歩的な質問でごめんなさい。
main = do
cs <- getContents
putStr.unlines $ lines cs
これはコンパイル通るんですが
main = do
cs <- getContents
putStr.unlines.lines cs
これは通りませんでした…これって何故なんですか?
てっきりlinesとunlinesというのは対になってるもんだと思ってたんですが…
0213デフォルトの名無しさん
2007/11/18(日) 16:50:06なら通るよ。
関数適用とか演算子の優先順位の問題だね。
f $ g x == f . g $ x /= f . g x
0214デフォルトの名無しさん
2007/11/18(日) 16:55:54「putStr.unlines.lines cs」の部分が
putStr.unlines.(lines cs)
って解釈されるはず
main = do
cs <- getContents
(putStr.unlines.lines) cs
ならたぶん通る
0215デフォルトの名無しさん
2007/11/18(日) 16:58:160216デフォルトの名無しさん
2007/11/18(日) 17:00:370217デフォルトの名無しさん
2007/11/18(日) 17:09:39まあ>>215をあまり真に受けないでくれ
0218デフォルトの名無しさん
2007/11/18(日) 17:23:42f.g x.h のように関数が引数を持つ場合にやるとなんか微妙
0219デフォルトの名無しさん
2007/11/18(日) 17:25:16こう決めた理由はあるの?
0220デフォルトの名無しさん
2007/11/18(日) 17:25:37思ったら、数学の教科書とソックリです。
つまり、Haskellは数学ができる人向けってことでしょうか?
0221デフォルトの名無しさん
2007/11/18(日) 17:31:13うお、通りました。ありがとうございます。
関数合成と関数適用の優先順位の問題だったんですね。
0222デフォルトの名無しさん
2007/11/18(日) 18:15:00関数適用最強の原則を守るためじゃないか?
俺は現状で満足だ。
map (fromMaybe 0 . fst) xs
とか書けるし。
0223デフォルトの名無しさん
2007/11/18(日) 18:34:32うざい括弧をつけなくて済む
0224デフォルトの名無しさん
2007/11/18(日) 20:16:16↑↑うざい括弧
0225デフォルトの名無しさん
2007/11/18(日) 20:23:030226デフォルトの名無しさん
2007/11/18(日) 20:42:38C言語風には f(g(x))
うざくない?
0227デフォルトの名無しさん
2007/11/19(月) 03:14:41このページの2007-07-04の日記を参考にプログラムを書いているのですが
これで横型探索できる理屈がまったくわかりません
0228デフォルトの名無しさん
2007/11/19(月) 03:39:03instance Monad (State s) where
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
↑の式でm >>= k が m >> kなら、右辺は
State $ \s -> let
(a, s') = runState m s
in runState k s'
((k a)がkだけになる)
という風になると考えていいんでしょうか?
0229227
2007/11/19(月) 04:04:210230デフォルトの名無しさん
2007/11/19(月) 04:24:37それでOK。
ただm >>= kとm >> kのkはそれぞれ別の型だってことに注意。
m1 >> m2 = m1 >>= const m2 なので k=const m2 と考えると
runState (k a) s'
= runState ((const m2) a) s'
= runState m2 s'
0231228
2007/11/19(月) 10:59:03>>=が一つだけならなんとか頭で理解できるんですが>>=が二つ以上ならんでいたり
do式で表されていたりすると脳味噌が追い付きませんorz
0232143
2007/11/19(月) 23:12:23<ターゲット、ホストに共通>
デフォルトサーチパスにGNU MPがない場合は--with-gmp-{includes,libraries}で指定する必要があるが、
途中からこの指定(ライブラリサーチパス)を見てくれなくなる上、
できあがったGHCでも-Lオプションを指定しなければいけなくなるので
(少なくともlibgmp.so.*かlibgmp.aファイルのどちらかを)デフォルトサーチパスにシンボリックリンクしておくほうがいい。
<ホスト>
ghc-6.6.1/Makefileの
echo ghc-$(ProjectVersion)/libraries/haskell-src/Language/Haskell/Parser.hs >> hc-files-to-go
という行を削除またはコメントアウトする必要がある。
libraries/Cabal/cabal-setup/CabalSetup.hsが作られないので、
cd compiler && make boot && makeの後、
cd libraries/Cabal/cabal-setup
rm CabalSetup.{o,hi} cabalsetup
../../../compiler/ghc-inplace -H16m -O -H32m -package Cabal -c CabalSetup.hs -o CabalSetup.o -ohi CabalSetup.hi -keep-hc-files
../../../compiler/ghc-inplace -o cabal-setup -H16m -O -H32m -package Cabal CabalSetup.o
する必要がある。
make hc-file-bundle Project=Ghcの前に、
make -C rts AutoApply_thr.hc AutoApply_thr_p.hc AutoApply_debug.hc AutoApply_thr_debug.hc
する必要がある。
続く
0233143
2007/11/19(月) 23:14:33<ターゲット>
いきなり/usr/localにインストールするのではなく、stage1のためのディレクトリにインストールして、
それを利用してもう一度ghcをビルドしたほうがいいと思われる。
*-hc-tar.gzをソースツリーにコピーするのではなく、展開されるghc-6.6.1を手動でソースツリーに上書きする必要がある。
distrib以下のスクリプトに実行権限を与える必要がある。
hc-buildが完了した後、
cd compiler
rm -f *.hs-incl
make primop-can-fail.hs-incl primop-commutable.hs-incl primop-data-decl.hs-incl
primop-has-side-effects.hs-incl primop-list.hs-incl primop-needs-wrapper.hs-inc
l primop-out-of-line.hs-incl primop-primop-info.hs-incl primop-strictness.hs-inc
l primop-tag.hs-incl primop-usage.hs-incl
find . -name \*.o -exec rm {} \;
make boot stage=1 && gmake stage=1
cd ..
make install stage=1
で完了。
ちなみにザウルスのOpenBSD上では16MB以上のテキストセグメントがある実行ファイルは実行できないので
テキストセグメントを32MBに拡張したカーネルを使用しなければビルドできませんでした。
GNU makeがmakeという名前以外(gmakeなど)でインストールされている場合は、適宜読み替えてください。
かなり効率の悪い方法なので、Makefile等をちゃんと読めばもっと最適化できると思います。
古いGHCで新しいGHCをビルドするのはうまくいきますが、
新しいGHCで古いGHCをビルドするのはなかなかうまくいきませんね。
0234デフォルトの名無しさん
2007/11/20(火) 08:39:00例えば
add x y = x + y
という関数があって、一度
add 1 2
という式を評価した後もう一度
add 1 2
を評価しようとするとき、内部では律儀に 1 + 2 を行うんでしょうか?それとも
add 1 2 = 3
みたいな式が内部で作られてたりするんでしょうか?
0235デフォルトの名無しさん
2007/11/20(火) 09:30:04俺が知ってるのは
f x a b c = a*x*x + b*x * c
という関数に対して
f (1+2) 3 4 5
と呼び出した場合に1+2が1度しか評価されないことくらい…
0236デフォルトの名無しさん
2007/11/20(火) 10:20:01Haskellの規格では規定されてないけど、普通は評価しなおす。
関数を全部メモ化していたら、救いようのないメモリリークが起こるはず。ただし、
map (\x -> x * add 1 2) xs
のようなコードが最適化されて
let _z = add 1 2 in map (\x -> x * _z) xs
になって、add 1 2が一回しか計算されない、という場合はある。
0237デフォルトの名無しさん
2007/11/20(火) 11:41:31コンパイラのコンパイルオプションによっても動作が違うかな
import System.IO.Unsafe
f n=seq (unsafePerformIO $ putStrLn "hello") n
a=f 1+f 1
main=print a
のようなコードだとGHC6.6.1の場合で最適化なしの場合とありの場合でhelloの表示回数が違ったりする。
0238237
2007/11/20(火) 11:44:46a=f 1+f 2
でも最適化ありで1回表示、 無しで2回表示でした。
0239デフォルトの名無しさん
2007/11/20(火) 18:31:21ドラキュラとかが眠ってそうな感じの、棺おけ型のベッドというのは市販されているのでしょうか?
冬の暖房の時期に、部屋ごと暖めるのでは効率が悪いので、棺おけの中だけ温度調節できれば
コスト安になると思ったのです。
また、フタをつけるので静かですし、明かりもシャットアウトできてよいと思うのです。
0240デフォルトの名無しさん
2007/11/20(火) 19:04:23(計算をデフォルトで遅延させる機能のある、関数型のプログラム言語は市販されているのでしょうか?)
冬の暖房の時期に、部屋ごと暖めるのでは効率が悪いので、
(評価されない可能性のある式を正格に評価するのは効率が悪いので)
棺おけの中だけ温度調節できればコスト安になると思ったのです。
(必要になってから評価できれば計算コストを削減できると思ったのです。)
また、フタをつけるので静かですし、明かりもシャットアウトできてよいと思うのです。
(一度評価されればメモ化されるので計算量が少なくなりますし、バグの混入もシャットアウトできてよいと思うのです。)
答え:Haskellは無料で公開されています
こうですか!? わかりません!
0241デフォルトの名無しさん
2007/11/20(火) 19:27:370242デフォルトの名無しさん
2007/11/21(水) 04:31:54GHC6.8.1にはHGL入ってないんですか?
0243デフォルトの名無しさん
2007/11/22(木) 01:59:38Win32モジュールにはSetLayeredWindowAttributesのラッパは入ってないんだな・・
自作するしかないんだろうか。
0244デフォルトの名無しさん
2007/11/22(木) 07:26:410245デフォルトの名無しさん
2007/11/22(木) 12:20:00>書いてパッチを送るんだ!
いや、これってwindows2000以降の機能で、Win32モジュールに入れるべきかどうか正直迷うんだよね。
0246デフォルトの名無しさん
2007/11/22(木) 23:16:48ツッコミなどよろしく。
0247デフォルトの名無しさん
2007/11/23(金) 09:58:22Windowsに詳しくないので間違ってたら済まんが、2000以降のみの関数も
普通にwin32パッケージに入ってないか?setConsoleCPとかfindFirstChangeNotificationとか。
>>246
どこに置いたかも書けよw
0248デフォルトの名無しさん
2007/11/23(金) 10:06:51場所は、わかるだろ。
0249デフォルトの名無しさん
2007/11/26(月) 23:05:20既存の流行している言語は対応できてないと。
これはどういう理由でしょうか?遅延評価とか、その辺のことを指しているんでしょうか。
0250デフォルトの名無しさん
2007/11/26(月) 23:13:400251デフォルトの名無しさん
2007/11/26(月) 23:23:18一人歩きしてるだけじゃないかな。実際には何をするにも副作用は
あるし、MapReduce だって Reduce の作業はスケーラビリティが
殆ど無いか少ない。関数型言語には副作用が無いというのと同じ様な
勘違い。ただ副作用が無い=スケールする部分を奇麗に切り出せる
のであれば有用ではある。
0252デフォルトの名無しさん
2007/11/27(火) 11:43:41>>249の話は伝聞なんで雲を掴むような話だけど。
0253249
2007/11/27(火) 11:48:13遅延評価っていうのは、別に関係ないんでしょうか。何かそっちの話を聞いた
ことがあるんです。自分の初心者脳では、正格では無限のリソースを前提に
した関数を書けないが、Haskellのような言語だと記述可能、とか思ったのですが、
ちょっと頭悪いですか?w
0254デフォルトの名無しさん
2007/11/27(火) 12:16:38CPUコアの利用効率を上げられますが、
それには頭のいいスケジューラが必要なわけで。
例えば、
http://www.fixstars.com/Grid/pukiwiki/index.php?MapReduce
にプチ解説があるようなstragglersの問題。
ただ実行順序が規定されてないので、
工夫する余地がまだまだ残されているとは言えると思う。
Erlangのような言語が、あまりpure functionalじゃないとはいえ、
一通りの実績を上げていますし。
また、プログラマがスケジューラに自由を与えるような
プログラミングスタイルを強制されているという見方もあると思う。
0255デフォルトの名無しさん
2007/12/06(木) 10:41:19関数型で今イチバン売れ筋なのはF#なんですかね。
0256デフォルトの名無しさん
2007/12/06(木) 17:36:48・概念的にはMonadよりArrowのほうが分かりやすいんじゃないか?とか。
・Monadって何?って聞かれるとなんと答えていいかわからないが、
Arrowなら『矢印をカプセル化したようなもの』と言える。
あとは適当に結合演算とか普通の関数をアロー化する演算とか実装していけばおk。
脳内のイメージも矢印をつないでいくだけだし。
Monadをイメージしようとしてもなんかいまいちピンとこない……。
bindにやる夫関数とか適当に名前を付けて無理矢理イメージしたけど。
・Monadのbind演算子(>>=)はm a -> (a -> m b) -> m bで非対称的。
Arrowの(>>>)はa b c -> a c d -> a b dで比較的対称性があって気持ちよい。
・Arrowは『計算を結合』しているのが自明的に表現されてる。
Monadは別にそうは見えない。……値と計算を結合なのか?意味わかんね。
・そもそも非対称な二項中置演算子はイマイチ気に入らない。
リスト結合演算子とか`elem`とかは仕方ないけど、せめてあまり高階にしてほしくない
・Monadの計算部(a -> m b)は結構重要なパーツの一つなのに、名前が付いてない。
だから『モナドを返す関数』としかいえねえ。
しかもbindした後にはその返り値とは(型は同じだけど)別の奴が帰ってくる。無駄に混乱。
その点Arrowは計算部がずばり『Arrow』。カプセル化されていて美しい。
・Monadは(>>=)は左から右へ流すように使えるが
普通の関数は右から左。もちろんliftMとかも右から左。
(=<<)も右から左。しかし関数を拡張して適用するという見方で見るとこっちが自然という謎さ。
結局どっちからどっちへ読むべきか迷う場所が多く、思考停止してしまう。
ArrowだったらArrowとして結合されている部分は左から右。
普通の関数は右から左で思考が自然に切り分けられる。
0257デフォルトの名無しさん
2007/12/06(木) 17:37:32Arrowはまあ基本的にポイントフリーな感じがするし、普通の関数と分けられていいんじゃない?
・Arrowの構造を作ったりする関数は基本的にArrowだけを返す。
Monadの関数はなんかリストとかに入ってたりして気味が悪い。モナドのリストって、最中十個入りじゃないんだから。
・Arrowの構造を作る関数はキチンと構造を作ってるように見える。
Monadの場合は解読に時間がかかる。なんのためにこんな書き方をしてるんだろうとか……。
・ArrowでStateを自作してみたら比較的分かりやすかった。
Monadのは今見ても訳が分からん。というかMonadの対象が関数って何だよ。
・Monadに慣れ親しんでる人はMonadを扱うのに苦労しないだろうから、
簡単なものなら短い表記が出来るMonadのほうがいいんだろう。
しかし、初心者にいきなり教えるのならArrowのほうが直感的。
ポイントフリースタイルを使いまくってムツカシイことさえしなければ。
・Arrow講座みたいな入門編とかでArrowを書くとき、
関数がそのままアローになるからってやたら省略しないでいただきたい。
アローな部分と普通の関数の部分が綺麗に分かれてるのがいいんだから……
それにarrってやっておけばその部分は一般のArrowでも使えるし。
SF f >>> SF g = SF (f >>> g)とか出来るからそういう書き方が出来ること自体はありがたいが。
・arr.uncurryとかarr.constってよく出てくるけどそういう関数はないのか……
・Arrow関係ないけどデータ構築子と型構築子が同じ名前って混乱するな。時々イラっとくる。
・aとかbとか何を表してんのか直感的じゃねえよ。型変数だったり、引数だったり……
fって名前だから関数かと思いきやArrowだったり。
ネーミング規約みたいなものはないのか……
Arrowが引数で来たときの名前の付け方とかおもいつかねえけど。
・そろそろふつける買おうかな……。
・初心者のくせに身の程をわきまえない長文失礼しました……
0258デフォルトの名無しさん
2007/12/06(木) 17:42:34> ・Monadでポイントフリースタイルをやろうとするとかなりキモくなるよね。
もう少し他人のコードを読んでいくと感覚がつかめてくると思いますよ
0259デフォルトの名無しさん
2007/12/06(木) 18:11:18しかし「モナドのリスト」って言い方は何か違和感あるな。
[IO]みたいなのを想像してしまう。
0260デフォルトの名無しさん
2007/12/06(木) 18:16:500261デフォルトの名無しさん
2007/12/06(木) 18:25:06把握。
>>259
ライブラリを見返してるけどそこまではなかったかも……。
初めて見たときに比べればそこまで疲れないし。
やっぱり慣れの問題なんだろうか。『モナドを返す関数』が普通の関数と同じ地位にいるのがイマイチだけど。
引数の数でバージョンがいくつもあったりするのもなんかいただけない。
でもやっぱり慣れれば気にならなくなるんだろうな……。
なんかJavaやったらCのポインタが理解できた時の気持ちを思い出した。(違うか)
0262デフォルトの名無しさん
2007/12/06(木) 18:30:020263デフォルトの名無しさん
2007/12/06(木) 18:30:440264デフォルトの名無しさん
2007/12/06(木) 18:38:36日本語だと「モナドな関数」か。
俺のコードの大部分はモナドな関数になってるな。
普通の関数より書きにくいから嫌なんだが、変更に強いコードにするために仕方なく。
0265デフォルトの名無しさん
2007/12/08(土) 12:05:09http://www.sampou.org/haskell/tutorial-j/classes.html
> (ここで、同値性といっているのは、「値同値性」のことです。
> 対照的な概念としては、「ポインタ同値性」というのがあります。
> たとえば、Java 言語の == です。
> ポインタ同値性は参照透明性を持ちません。
> それゆえに純粋な関数型言語とは相性がよくありません。)
なぜポインタ同値性は参照透明性を持たないのですか?
0266デフォルトの名無しさん
2007/12/08(土) 12:26:42ポインタ同値をテストする関数eqがあったとすると、
let v = [1,2] in eq v v
はTrue。一方、vを展開して
eq [1,2] [1,2]
とするとFalseになるかもしれない。
参照透過って言うのはそもそも、こういう展開をしても
プログラムの意味が変わらないってことだから、
eqによって参照透過性が破られたと言える。
0267265
2007/12/08(土) 12:37:55おー!なるほど。わかりやすい説明ありがとう。
[1,2] が複数箇所に出現する場合、メモリ上に別々に配置されるかもしれないわけですね。
勉強になりました。
0268デフォルトの名無しさん
2007/12/09(日) 15:29:39Aは型構築子、全体は多相型、aはパラメータ
Aはデータ構築子、全体はデータ構造、aはその中身
aは型クラスAのインスタンス、何かの型の一部
って変わるのがちょっとわかりにくいね。もうちっとなんとかならんか。
0269デフォルトの名無しさん
2007/12/09(日) 21:35:19乱数生成器をsplitしていくつかにしてseed固定で乱数を作れといわれました。
どう作ればいいんでしょうか?
初歩的な質問だったらすみません。
0270デフォルトの名無しさん
2007/12/10(月) 00:51:190271デフォルトの名無しさん
2007/12/10(月) 15:07:15でも無限リスト型を再定義するとリストに関して作ったすべての関数について委譲関数を作んなきゃいけなくて現実的じゃない。
結局これは妥協するしかないのか?それともなんらかのテクニックで回避できる?
0272デフォルトの名無しさん
2007/12/11(火) 10:46:48日本語でおk
0273デフォルトの名無しさん
2007/12/11(火) 10:52:25俺の知る限り、妥協するしかない
0274デフォルトの名無しさん
2007/12/11(火) 12:46:45評価がとまらないだけで型安全だよ。
■ このスレッドは過去ログ倉庫に格納されています