迷いませんか?

プログラミング、電子工作、ゲーム・・・etc、色々やるけど中途半端なブログです。

関数プログラミングむずい

むずかしすぎます(^q^)
関数プログラミング珠玉のアルゴリズムデザインというの読んでるんですけどね
ネット上のレビューを見たところ難しいとか書いてたんですけど
そのぐらい余裕とか調子乗ってたんですよ

現在4章よんでますが3章はすこし思考を放棄しました
鞍型探索って出てきて最初は理解してたんですが、
計算量を考え始めた時から対数とか知らないし、
T(〜〜) = 〜〜 とか出てきてもう式の変形すらわけわからないしで、
普通の中学生には難しすぎた

多分、高校3年生ぐらいの数学力があれば
スラスラとまでは行かなくても読めるのではないでしょうかね

僕は圧倒的に知識が足りないですが、
もうあるもんは仕方ないですし、面白いので努力して読みます

すごいH本もいよいよ大詰め!

一昨日と昨日は食い過ぎかなんかわかりませんが異常に腹が痛く気持ち悪かったです

あと先週ぐらいに某芋氏をリスペクトしてぱく・・・してgithub.ioでホームページを作る準備しました。
いやー、いろいろとなんかコミットとかプッシュできなくてビビったけどできてよかったです。
全然出来てないけど

そして今日は妹の運動会!これは見に行かねば!
しかしプログラミングの勉強したいから見に行かなかった!



午前中はずっとすごいH本を見ていて14章を終わらせました。
最後の演習問題ね、むずかしいよ、なんなの?
>>=ってモナド値を一般の値をとってモナド値を返す関数に渡せる関数じゃなかったんですか?
なんなのもう・・・
予想できなくてね、適当に
merge :: Prob Bool -> Prob Bool
とかの関数作ってみてもうまく動かんくてうーんってなるし、
結局のところ他人のブログを見るという最低な行為をした結果最初のアプローチで根気よく続けていれば成功してた。
成功してたんだ!だから!だから見たことは関係ない・・全部僕が考えたってことに・・・

なんないですよねー
まあいいや完成品のコードはこちらです

merge :: Prob Bool -> Prob Bool
merge (Prob xs) = Prob $ (foldl sumRatio [(True, 0%1), (False, 0%1)] xs)

sumRatio :: [(Bool, Rational)] -> (Bool, Rational) -> [(Bool, Rational)]
sumRatio [(True, tr), (False, tf)] (x, r) 
    | x == True = [(True, tr + r), (False, tf)]
    | otherwise = [(True, tr), (False, tf + r)]

ほぼパクリですよすいませんでしたね−!
けど僕の最初はfoldlのアキュムレータを別のにしてたりsumRatioの型宣言が違ったりしただけで
ほとんど同じなんです・・・信じてください・・・

まあこれが終わったらHakyllの勉強してサイト作成に励んでいきたいと思っているので
一切期待しないでお待ちくださらないでください(間違った敬語の可能性があります)
yesodもやりたかったけど公開するのにheroku必要感あってやめた

それでは

すごいH本 演習 13.6

本日3度めの投稿
しかたないじゃん、書きたいことがたくさん出来たんだから

すごいH本を読んでたら時々”これは読者への演習問題とします”的なのがある
だけどあまり取り組んでなかったので取り組んでみた
モナドむずいらしいし

まず基本的なin3とかの関数はできてる状態
ここでもともとのcanReachIn3にある(6,2)->(6,1),(6,2)->(7,3)
の2つを試してみることにした

とりあえず当てずっぽうにコードを書いてみる

canReachIn3 :: KnightPos -> KnightPos -> [KnightPos]
canReachIn3 start end
    | end `elem` in3 start = do
    | otherwise            = []

これで枠組みはできた感じだと思って成功する場合を考えてみる
ここで成功した時の情報の保持方法わかんねwwwどうしよwww
とかなってたけど普通に非決定性計算を行ってガードすればオーケーだとおもう
なので

    ~~ = do
    x <- return start
    y <- moveKnight x
    z <- moveKnight y
    a <- moveKnight z
    guard (a == end)
    return [x,y,z,a]

成功したと思ってたんですが
ghciからロードするとずらずらーーっとエラーが出て来て小少数の一名の方が混乱の渦に
??????????
とりあえずモナド的にghciでやってみるか

return (6,2) >>= \x -> moveKnight x >>= \y -> moveKnight y >>= 
    \z -> moveKnight z >>= \a -> guard (a == (6,1)) >> return [x,y,z,a]

パースエラー!!

ああ、そうだった最初のを括弧で囲わなくちゃ
そして実行すると・・・成功!
これで経験が少ない僕はさらに混乱が深まる

うーん・・・return外すとどうなるんだ???
と、長い間考えて出てきた駄思い付きを実行してみる・・・
エラーが・・・おきない? なんてこった!何が起こったっていうんだい?
実行してみると
[(~~),(~~),(~~),(~~),. . .]
わかりにくい! 4つ区切りで答えになってるのはわかっても見にくいよ!
なんか前の方で使ってたgroupsOfを使ったらエラーが起きるしわけわかめ

そういや・・・ghciでやった時は・・・[[(~~),(~~),(~~),(~~)],. . .]ってなってたな・・・
・・・!?
returnやgroupsOfでリストのリストにできない!しかしghciでやると実行できる!
もう一度コードを見なおしてみよう!どこかに間違いがあるはずだ!!!

・・・あった!型の宣言で[KnightPos]になってた!これを直せば・・・成功!最高!

型エラーはめったにないって本に書いてたから勘違いしてました(責任転嫁)
とりあえず完成したコードはこちら

canReachIn3 :: KnightPos -> KnightPos -> [[KnightPos]]
canReachIn3 start end
    | end `elem` in3 start = do
        x <- return start
        y <- moveKnight x
        z <- moveKnight y
        a <- moveKnight z
        guard (a == end)
        return [x,y,z,a]
    | otherwise = []

しっかりと型の宣言も見なおそうね!またいつか!

モノイドとかいろいろなのの定義

モノイドは結合法則がなりたち、単位元がある演算子&要素?みたいなことがあって
これって数学ガールで見たけど群だwwwwひゃっほーーーうwwww
と思ったので調べてまとめたのをブログに書く

よく考えたら群ってもうひとつぐらい性質なかったか?

   _人人人人_
   > 逆元 <
    ̄^Y^Y^Y^ ̄

wikipediaを見るとモノイド=半群的なことが書いてあった(勘違い)
じゃあ半群の性質は? A.結合法則

あれ?なんか違うかも?
モノイドのページをしっかりと見てみると、
いろいろとわかりにくく書いてるけど結合法則単位元だった。

そして群は最初に調べたからわかるけど結合法則単位元、逆元の3つ

wikipediaのページって専門的に書いててどういう性質かってのが簡単にわからなかったから書いた、ただそれだけ

まとめると

結合法則     ->半群
結合&単位元   ->モノイド
結合&単位元&逆元->群

こう見るとモノイドって名前が場違いに感じるな、三分の二群とかなかったのか(かっこわるい)

bracket,bracketOnError

bracketとbracketOnErrorの処理がよくわからなかったのでまとめる

bracketは
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
( (a -> IO b)に当てはまる関数をf,(a -> IO c)に当てはまる関数をdとする)
という型になっていて、
まずdを処理します。
そしてその後fを処理するというようになっていて、
最終的にIO cを返すということで正しいはず。
このとき、エラーが起こるとfを実行し確実にリソースの解放を行う。
リソースというのはハンドルなどのこと

なので順番的にはd, f と実行してIO cを返すが
エラー時にはfを実行してリソースを解放する。

bracketOnErrorは、型はbracketと同じで
bracketOnError :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
となっているが、bracketとは処理の方法が違う(方法というか順番?)
bracketでは確実にdの後にfを処理していたが
bracketOnErrorではdのあとは何も処理せずIO cを返す。

このため、bracketでは解放する処理をfにだけ書いておけばよかったが
bracketOnErrorでは、それだと解放されなくなるので
dの方にも解放処理を書かねばならなくなり面倒くさくなる。
しかし、これにより普段は実行したくないけどエラー時はエラーを知らせるなどの
処理ができるようになるところにメリットがあるんじゃないかなと思う

どうせこの考えは間違ってそうなのでだれか指摘ちょーだいლ(╹◡╹ლ)