1 名前:デフォルトの名無しさん [2020/02/10(月) 18:17:36 ID:L6eYQqyh.net] 関数型プログラミング言語 Haskell について語るスレです。 Haskell Language(公式サイト) https://www.haskell.org/ 日本Haskellユーザーグループ - Haskell-jp https://haskell.jp/ 前スレ 関数型プログラミング言語Haskell Part32 https://mevius.5ch.net/test/read.cgi/tech/1548720347/
670 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 17:07:44.96 ID:aAR5bcpB.net] >>660 いわれてみればhaskell触るまでこういう特徴が泣くほどうれしいなんて思ってなかったなぁ……
671 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 17:39:40.94 ID:kKr2IDUq.net] >>660 利点を提示っていうかLispとHaskellの違いを提示する必要がある Lispの利点を再現するだけならPythonで十分な気がする しかしHaskellを再現できるものがまだ出てこない それは関数型じゃなくて静的型の説明をしないと意味が分からないと思うけど
672 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 18:38:17.88 ID:apYLuAz7.net] >>662 ありがとうございます そうなんです 今のところそれしか解決策ないんです しかし希望では IO [ Int ] であって欲しいんです イメージとしてはこうです ある関数 f があって乱数で挙動が変わって欲しい もちろん最終的にはIOモナドを使わないとしょうがない しかし色々いじってる段階ではモナド被せないで代わりに擬似乱数無限配列 psuedRand :: [ Int ] みたいなのを食わせて f a b c psuedRand みたいに呼び出して色々頑張って、最後の最後にIOモナドで実地に ( return . f a b c ) =<< realRand に切り替えるみたいな事ができないかなと思ったんです f が使用する乱数がある程度わかるので別に無限列でなくてもいいっちゃいいんですけど 今一歩モナドに包まれてる関数いっぱい出てくるの好きじゃないんですよ 通のホムペとか見てるとむしろバンバンモナドでくるんどいた方がいいみたいなのもみるんですけどねぇ
673 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 18:57:39.14 ID:IzsyJlfZ.net] >>665 そうなのかあ。 すまない、俺では力不足のようだ。
674 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 19:04:15.17 ID:apYLuAz7.net] >>666 いえいえ、ありがとうございます 考えていただいて感謝です🙏
675 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 20:02:19.54 ID:kKr2IDUq.net] headやtailの戻り値の型はIOではないって宣言してるから リスト処理中にrandomIOができなかったとしても不思議ではない 型を宣言するってそういうことよ
676 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 21:15:09.40 ID:jArj32vs.net] >>665 やりたい事の本質がいまいち分かりません。 2点確認します。 ひとつめ。 結局のところ今は [a] 型の乱数を返す関数を作りたいのでしょうか。 それとも、IO [a] 型の乱数を返す関数を作りたいのでしょうか。 はたまた、両方でしょうか。 ふたつめ。 開発環境では > f a b c psuedRand 本番環境では > ( return . f a b c ) =<< realRand という事でしょうか。 前者は純粋関数の式、後者は IO モナドを伴う式です。 これは、本番環境で IO モナドな関数を、開発環境では純粋関数で開発するという事ですよね。 開発環境を本番環境にする際には、後者の式を呼び出している外側の関数も、 純粋関数から IO モナドに書き換えるのでしょうか。 あまりお勧めしません。 本番環境で IO モナドな関数は、開発時も IO モナドで開発&テストした方が良いと思います。 環境が違ってもインターフェース(型シグネチャ)はそろえた方が良いです。 事情がおありなので、あくまで私は勧めないというだけですけど。
677 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 21:21:29.93 ID:apYLuAz7.net] >>668 まぁそうですね できんもんはできんのでしょうね ただ出来るか出来ないかの判定がまだまだ自分の実力不足でできないのか、実際禁止されててできないかのか判断がつかないんです >>669 やはりそうなんでしょうね まだまだ初心者でいまひとつモナドで包まれてるの馴染みがないので避けれるなら避けたいと思ってしまいます この場合はモナドで最終的にくるむなら避けられても避けるべきではないのでしょうね
678 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 21:52:28.04 ID:kKr2IDUq.net] >>670 型を書かない言語も普通に存在するので、型を無視する方法があってもそれも不思議ではない
679 名前:デフォルトの名無しさん mailto:sage [2021/01/20(水) 23:15:01.74 ID:Sb+ElJSJ.net] >>671 まぁ今回のは諦めます 出来るのなら見つけたホムペの人が紹介してくれてただろうし
680 名前:デフォルトの名無しさん mailto:sage [2021/01/21(木) 00:38:31.39 ID:HkuQh/W6.net] >>660 副作用とか純粋関数の話は単体テストの話題と絡めたいね それが通じなかったら知らん 部分適用というか高階関数の話は コールバックとかイテレータのような「処理の抽象化」が 極めて書きやすくなるというような話でどうか
681 名前:デフォルトの名無しさん [2021/01/21(木) 06:01:52.78 ID:mwzMDOkA.net] Haskellで厳しく性能を最適化しようとすると 抽象的なところで実装を意識したコードを書くことになって苦労する みたいなレビューがあった Haskellはベンチ結果良いように見えて その手の「実装を意識したコード」がベンチ用に書かれるからで 実際は割と遅めなんだな
682 名前:デフォルトの名無しさん mailto:sage [2021/01/21(木) 06:07:07.88 ID:LkrjH2wS.net] >>674 そのレビューのURLを貼っていただけないでしょうか
683 名前:デフォルトの名無しさん [2021/01/21(木) 06:30:57.22 ID:mwzMDOkA.net] https://stackoverflow.com/questions/35027952/why-is-haskell-ghc-so-darn-fast この辺 > thanks for the link. 80 lines is what I called "low-level style of programming not much different than programming in C itself." . "the higher level code", that would be the "stupid" fmap (length &&& length . words &&& length . lines) readFile. If that was faster than (or even comparable to) C, the hype here would be totally justified then. We still need to work hard for speed in Haskell as in C, is the point. >>612 もそんなことをかいてる
684 名前:デフォルトの名無しさん [2021/01/21(木) 06:38:11.58 ID:mwzMDOkA.net] 以下の厳密というのは遅延評価じゃなくするという事だろう? しかも「プロファイルを作成して改善」は一度アプリを書いてから実行の様子を観察して最適化していくという事だろう。 抽象的にHaskellらしく書いていきなり速いというわけではないという事だ。 プロファイラーでボトルネックを特定して特殊なコードに変えていけば速くなる、と。 >はい、怠惰はおそらくナイーブなHaskellが遅い最大の理由であり、 最適化されたHaskellでさえ速度の点で信頼できない可能性があります。 そのため、パフォーマンスが重要なアプリケーションにはお勧めしません。 OCamlの方が適しています。繰り返しになりますが、 HaskellをBangPatternsなどで厳密にすることはそれほど難しくありません。 また、コードの読み取りや保守が難しくなることもありません。 したがって、パフォーマンスが望ましいが、遅いプロトタイプでも問題がない場合は、 Haskellが非常に良い選択です。うまく機能するものを一緒にハックしてから、 プロファイルを作成して改善します。
685 名前:デフォルトの名無しさん [2021/01/21(木) 08:18:51.22 ID:mwzMDOkA.net] こういう認識 ・Haskellはコードだけでは最適化ポイントを見つけれない ・最適化したら変なコードになる ・普通のHaskellコードはベンチで他言語に惨敗する
686 名前:デフォルトの名無しさん [2021/01/21(木) 09:21:08.07 ID:mwzMDOkA.net] これも ・最適化の方法が処理系(GHC)次第で決まり、プログラマーの認識内に無い。 GHCに対してひたすらトライアンドエラー
687 名前:デフォルトの名無しさん mailto:sage [2021/01/21(木) 21:44:08.46 ID:AWFMWVQb.net] ・Haskellが欲しかったポジションはなんかPythonにとられてしまった
688 名前:デフォルトの名無しさん mailto:sage [2021/01/22(金) 00:20:12.86 ID:IysdrbOG.net] HaskellとPythonは似ていないから両方使ってもDRYに違反しない 似たもの同士で馴れ合い、異質なもの同士を分断するやつは信用できないが Pythonは似たもの同士でしっかり競争して生き残ったやつだから信用できる
689 名前:デフォルトの名無しさん mailto:sage [2021/01/22(金) 01:34:45.31 ID:Zh6FWeVu.net] pythonがなかったとしてもhaskellがそのポジションになることはなかっただろう
690 名前:デフォルトの名無しさん mailto:sage [2021/01/22(金) 02:27:11.57 ID:XLcorGPG.net] 欲しかったHaskell ・型を最大限に活用、バグが無いことを保証しつつ自然にC言語並みの性能も出る
691 名前:デフォルトの名無しさん mailto:sage [2021/01/22(金) 08:04:15.32 ID:RWrydEj5.net] Haskellerのキモオタ「シグネチャァ」
692 名前:デフォルトの名無しさん mailto:sage [2021/01/22(金) 12:35:37.28 ID:Erx3tlcS.net] 醜悪な表現が得意な奴って、綺麗な表現だとポエムとか言われる恐怖を煽られた結果なのかなと ふと思った
693 名前:デフォルトの名無しさん [2021/01/22(金) 18:29:59.60 ID:WeFjBpWyB] デキる人ほどフリーランス化する?★働き方改革 https://www.youtube.com/watch?v=ALflcwYOJtQ 年収890万円以下は社会のお荷物★騙される労働者 https://www.youtube.com/watch?v=CAp-ZrJpF54 騙されたくなかったら勉強しろ★他人のルールは損をする https://www.youtube.com/watch?v=s176O6qKuPw 底辺の99%は一生底辺★10年後が見えない同僚たち https://www.youtube.com/watch?v=4Mfiwn2sPD8 稼ぎたければ働くな★4千万円ぽっちも稼げないのはなぜ? https://www.youtube.com/watch?v=Fi7bILN4wes サラリーマン思考では儲からない理由 https://www.youtube.com/watch?v=iW6oAo0q0ZI 「頭使えよ貧乏人」に思う、寝てても金入るシステムを作る人 https://www.youtube.com/watch?v=VEB6M_s6abs
694 名前:デフォルトの名無しさん mailto:sage [2021/01/23(土) 13:17:02.46 ID:u7XOzuV6.net] >>672 ListT を使えばと思ったけどだめだった。 ・参考 https://blog.mudatobunka.org/entry/2018/01/03/233314 ・残骸
695 名前: module Rand2 where -- stack install list-t -- stack exec ghci import Control.Monad.IO.Class ( liftIO ) import ListT ( ListT, toList ) import System.Random ( Random(randomIO, randomRIO) ) t1 :: ListT IO Int t1 = return 3 t2 :: ListT IO Int t2 = liftIO (randomIO :: IO Int) t3 :: ListT IO [Int] t3 = repeat <$> t2 output :: ListT IO [Int] -> IO () output t3 = do li0 <- toList t3 print $ take 10 $ head li0 [] [ここ壊れてます]
696 名前:デフォルトの名無しさん mailto:sage [2021/01/23(土) 22:12:27.68 ID:u7XOzuV6.net] >>687 できたー! module Rand2 where -- stack install list-t -- stack exec ghci import Control.Monad.IO.Class ( liftIO ) import ListT ( ListT, toList, cons, take ) import System.Random ( Random(randomIO) ) t2 :: ListT IO Int t2 = liftIO (randomIO :: IO Int) t3 :: ListT IO Int t3 = do x <- t2 cons x t3 output :: IO () output = do li <- toList $ ListT.take 10 t3 print li {- *Rand2> output [7616927328998369033,6970782903781268443,-1509938769401207081,-2789264750098693865,-6524417077297424569,8403979199680420436,-3097298192134792937,-2736699795503652525,-4754186463647322678,5658901448509988002] -}
697 名前:デフォルトの名無しさん [2021/01/24(日) 10:57:12.77 ID:EEhZoft7.net] 自分の理解が根本的に間違ってるかもしれんけど haskellは宣言型で実効順序が定まっていないみたいな話を聞いたんだけど do記法は普通に上から下に実行されるというイメージになるの? main = do x <- readLn x2 <- readLn こういう風に書いた場合、最初に入力したものがxに入り、その順番は入れ替えれないはず do記法はほとんど命令型じゃないの? IOモナドとかに入力されていくアクション列はその順番を入れ替えれないよね? どんな感じでコーディングされてるか知らないけど 副作用があるところでは順番を入れ替えれないはず、即ち命令型と大差ないはず
698 名前:デフォルトの名無しさん mailto:sage [2021/01/24(日) 12:14:30.84 ID:3w4a632B.net] >>688 おお、できるんですか!? すげー 残念ながらいまListT使えないので環境整理してやってみます
699 名前:デフォルトの名無しさん mailto:sage [2021/01/24(日) 13:21:27.07 ID:vsDmG4Mq.net] >>689 do記法という言語機能は、上から下への命令の実行を記述するものではない モナドの組み合わせ方を宣言しているだけ IOのようなモナドの定義に対してはたまたま命令型言語のようになるだけ 言語レベルで命令を上から下へ実行しているわけではない
700 名前:デフォルトの名無しさん [2021/01/24(日) 15:49:32.04 ID:EEhZoft7.net] じゃあ標準入力から来た文字列の1行目と2行目を分けて扱うにはどう書くの?
701 名前:デフォルトの名無しさん mailto:sage [2021/01/24(日) 16:19:42.60 ID:QSDOehpN.net] ListT.toListの引数には有限のリストしか渡せないんだろう多分 現に li <- toList t3 print (take 10 li) ではなく li <- toList $ ListT.take 10 t3 print li と書いてある
702 名前:デフォルトの名無しさん mailto:sage [2021/01/24(日) 16:51:40.79 ID:o8L11MsB.net] >>693 > ListT.toListの引数には有限のリストしか渡せないんだろう多分 > 現に > li <- toList t3 > print (take 10 li) > ではなく > li <- toList $ ListT.take 10 t3 > print li > と書いてある 確認したところ、おっしゃる通り、 前者では応答が返ってきませんでした。 (ListT.repeat でも同じ結果だったので、t3 が悪いのではないです) > ListT.toListの引数には有限のリストしか渡せないんだろう多分 これで合っていると思います。
703 名前:デフォルトの名無しさん mailto:sage [2021/01/24(日) 23:50:31.64 ID:3w4a632B.net] やっぱり無理なんですかねぇ? 例えば以下は通るので ”IO 無限リスト” が原理的に無理なわけではないとは思うんですけど list = return $ repeat '3' main = do x <- list print $ take 10 x 何がどう違うもんなんでしょう?
704 名前:デフォルトの名無しさん mailto:sage [2021/01/25(月) 09:17:23.58 ID:xOoQiCMv.net] すいません 無限ランダム整数列の件ですが方法がありました というかSystem.Randomの中に最初から用意されてました 自作でランダム有限列作っておられた方のブログ見つけたので無限列なんて用意されてないとすっかり思い込んでました 以下の方法で1〜10の長さ100の乱数列が簡単に作れるようです 第一引数に値の範囲、第二引数に乱数の種を仕込みます 乱数の種は mkStdGen :: Int -> StdGen や getStdGen :: IO StdGen newStdGen :: IO StdGenSource で作成すれば良いようです 乱数の型はIntだけでなくDoubleなどでも作れるようです ---- import System.Random randomInts :: StdGen -> [ Int ] randomInts = randomRs (1,10) main = do ris <- ( return . randomInts ) =<< getStdGen print $ take 100 ris
705 名前:デフォルトの名無しさん mailto:sage [2021/01/25(月) 09:36:17.94 ID:lGPRZ7j1.net] 種が IO だから、 randomRs の戻りは [a] なんだね
706 名前:デフォルトの名無しさん mailto:sage [2021/01/25(月) 11:51:44.88 ID:crCxtFmd.net] ライブラリは暗記ですが、数学は暗記ですか?っていう定番のあれだな
707 名前:デフォルトの名無しさん mailto:sage [2021/01/25(月) 13:32:32.62 ID:/TZZteD8.net] >>692 newStdGen :: IO StdGenSource ↑ワロタw コピペするとよくあるわw
708 名前:デフォルトの名無しさん mailto:sage [2021/01/25(月) 13:33:07.46 ID:/TZZteD8.net] 安価ミス>>696
709 名前:デフォルトの名無しさん mailto:sage [2021/01/27(水) 00:16:50.20 ID:UiZI3fhW.net] dp の質問です haskell でdynamic programing する方法の例でFibonacci数列の計算を fib = 0:1:( zipWith ( + ) ( drop 0 fib ) ( drop 1 fib ) ) で計算させるというテクニックを紹介しているページがあってなるほどなぁと感心しました で同じテクニック使ってcomb6 !!i !! jが二項係数C[i, j]になる配列 comb6 = ( ( 1 : ( repeat 0 ) ) : ) $ zipWith ( zipWith ( + ) ) comb6 ( map ( 0 : ) comb6 ) を作ってみました コレはうまくいきます comb6 !! 2000 !! 1000 とかも一瞬で計算してくれます でcomb7 !! i !! j が二項係数C[ i+ j, i ]となる配列comb7を comb7 = ( ( repeat 1 ) : ) $ zipWith ( zipWith ( + ) ) ( comb7 ) ( tail $ map ( 1 : ) $ comb7 ) と定義してやってみると、compileまでは通るのですが実行comb!!1!!0すると<<loop>>と言われて止まってしまいます しかし手計算で展開してみてもloopしてないと思うんですけどどこがおかしいのかわかりません どなたかわかりませんでしょうか?
710 名前:デフォルトの名無しさん mailto:sage [2021/01/27(水) 11:32:01.04 ID:fGEABlaN.net] comb7 = x : xs xs = zipWith f comb7 ys ys = tail zs zs = map g comb7 zs = map g (x : xs) = g x : map g xs ys = tail (g x : map g xs) = map g xs xs = zipWith f comb7 (map g xs) -- ここで(map g xs)のパターンマッチができない
711 名前:デフォルトの名無しさん mailto:sage [2021/01/27(水) 12:36:29.90 ID:UiZI3fhW.net] >>702 ありがとうございます しかしどうもパターンマッチに失敗してるようではないようです 実際コンパイラは型推論に成功してるように見えますし、明示的に comb7 :: [[ Int ]] を入れてもダメです 実行時のエラーメッセージも Non-exhaustive patterns ではなく prog : << loop >> が表示されています
712 名前:デフォルトの名無しさん mailto:sage [2021/01/27(水) 13:52:31.92 ID:fGEABlaN.net] こういう時は自分の考えに自信を持つことも必要 誰かがエラーメッセージを見ている(または見ていない)のを見たからといって簡単に考えを変えない方がいい
713 名前:デフォルトの名無しさん [2021/02/01(月) 00:47:55.98 ID:TMv1Um3B5] 個人開発のWebアプリがツイッター世界トレンド1位になったけどいろいろ辛かった話vdeep.net/chocobox-back-story 【副業】個人アプリ開発の広告収入を公開します(?2020/11) https://cranklog.xyz/1586/ アプリ開発を個人で独学して収入を得る方法を現役エンジニアが徹底解説 https://yaba-blog.com/individual-development/ 【個人開発1年振り返り】リリースした7つのWebサービスの反省点と来年の活動について https://yukio.site/2019-web-services/ 個人開発のアプリで稼ぐのはそんなに難しいのかな? https://blog.httqs.com/log/101 個人開発者(副業サラリーマン)のアプリ広告収入を公開 https://sastd.com/developer-ad-revenue/ アプリ開発は稼げない?よくある勘違いや言い訳を徹底批判してみる https://apps.jp.net/introduction/excuse/ 個人がアプリ開発で収入を得る方法は4つ。だが甘くない! https://programming-school-hikaku.jp/column/application-make-money
714 名前:デフォルトの名無しさん mailto:sage [2021/02/02(火) 01:48:19.32 ID:yyMOWUoH.net] fixの定義は fix f = let x = f x in x となっていますが、 この x 自体は再帰的に定義されていると言えますか?
715 名前:デフォルトの名無しさん mailto:sage [2021/02/02(火) 16:19:31.38 ID:ErrealWs.net] >>701 xs0 = repeat 1 xs1 = zipWith (+) xs0 (0:xs1) xs2 = zipWith (+) xs1 (0:xs2) xs3 = zipWith (+) xs2 (0:xs3) こんな感じに個別に定義すれば確かに計算できるので、 comb7 !! 1 を計算するのにcomb7 !! 1 が必要だぞという点を 怒っているような気がするのだが確かなことは言えない、すまぬ comb6 !! n は計算するのに comb !! (n-1) の情報だけで十分なところが違うので
716 名前:デフォルトの名無しさん mailto:sage [2021/02/02(火) 17:58:42.89 ID:AZLuBdJH.net] >>706 再帰的と言うのは木構造を想定している気がする そのコードはグラフ簡約のためにそうなったので木構造でも再帰的でもないと思う
717 名前:デフォルトの名無しさん mailto:sage [2021/02/02(火) 22:40:39.64 ID:LQ6cge6d.net] >>707 ありがとうございます 私も多分それが原因かなと思い始めてます 一回目のcomb7 !! 1 と二回目では続く添字が! !!2 から !!1 に減ってるのですがHaskellはそんな事は勘案せずに「comb7 !! 1の展開の中にcomb7 !! 1が出てきたからアウト」と言ってるのかなと つまりはこの手の二重漸化式はHaskellはそのままズバリでは読んでくれないんでしょうね
718 名前:デフォルトの名無しさん mailto:sage [2021/02/03(水) 00:23:45.54 ID:QKvl77B6.net] comb7 !! 1 を計算するには length comb7 >= 2 のようなものが必要だぞ でも長さは1かもしれないからアウトという判断は正しい オーバーランするよりよっぽどいい
719 名前:デフォルトの名無しさん mailto:sage [2021/02/03(水) 14:08:13.61 ID:mxabq2OH.net] 求めてないかもですがこんなふうならかけますね。 module Main where import qualified Data.Array.Unboxed as AU main = do print $ comb6 !! 2000 !! 1000 print $ comb7_1 !! 1000 !! 1000 print $ comb7_2 1000 1000 AU.! ( 1000, 1000 ) comb6 = ((1 : (repeat 0)) :) $ zipWith (zipWith (+)) comb6 (map (0 :) comb6) comb7_1 = (repeat 1 :) $ ([ 1 .. ] :) $ (map (\x -> scanl (+) 1 $ tail x) $ tail comb7_1) comb7_2 :: Int -> Int -> AU.Array ( Int, Int ) Integer comb7_2 ly lx = comb7_2_table where comb7_2_table = AU.array ( ( 0, 0 ), ( ly, lx ) ) $ concatMap(\i -> map (f i) [ 0 .. lx ]) [ 0 .. ly ] f 0 x = ( ( 0, x ), 1 ) f y 0 = ( ( y, 0 ), 1 ) f y x = ( ( y, x ) , comb7_2_table AU.! ( (y - 1), x ) + comb7_2_table AU.! ( y, (x - 1) ))
720 名前:デフォルトの名無しさん [2021/02/04(木) 23:30:39.86 ID:OAJDFKMl5] サラリーマンの努力は資産にならない。 https://www.youtube.com/watch?v=3FLjm0Sn-2U ネットで稼げない残念な人の特徴 https://www.youtube.com/watch?v=sV_eyPfB7Wk 【継続=勝利】続けているうちに、周りは勝手に消えていきます。 https://www.youtube.com/watch?v=oe8rHWFlmVc 【危険】今すぐ逃げろ!ヤバい会社の特徴10選。 https://www.youtube.com/watch?v=N0JBhysIlzc 「ろくに勉強してこなかったバカ」が今日からすべきこと。 https://www.youtube.com/watch?v=3EUDu38W1Mw バカは「必要努力量」を見誤る。 https://www.youtube.com/watch?v=RG6_qkPhCuo
721 名前:デフォルトの名無しさん mailto:sage [2021/02/04(木) 22:24:53.84 ID:w5MK0dgi.net] >>711 ありがとうございます 参考にさせていただきます そうですね もう一つ可読性が欲しい感じがします 元々の問題意識としては私は可読性の高いコードが要求されることが多いのです 例えばFibonacci数列であれば f n = ( f $ n -1 ) + ( f $ n - 2 ) に可読性においてまさるものはないのですが、もちろんこれでは遅くて使い物になりません なので実用性も多少はなりとも求めるならある程度は可読性を犠牲にせざるを得ないのですが、どういう方法がいいのだろうというのがテーマなのです でたまたまFibonacciの場合に f = 0 : 1 : ( zipWith ( + ) f $ tail f ) というのを見つけてコレ中々いいなと、dpで計算してるのに“メモ”をするための不要な手続きを書く必要がなく、Haskellの“call by need”の機能をうまく利用してdp計算させてるところにちょっと唸ったもので でどれくらいコレでいけるのかなと二重数列をやってみたらうまくいかなくて、どうしたもんかなと まぁコレはしょうがないのかもしれませんけど
722 名前:デフォルトの名無しさん mailto:sage [2021/02/05(金) 00:47:44.85 ID:hZ1aOePg.net] >>713 方向性違うかなと思いつつ書いたんですがやっぱり違いましたね。失礼しました。 今更どうでもいいですがちょっと間違えたので訂正だけさせてください。 comb7_1 = (repeat 1 :) $ (map (scanl (+) 1 . tail) $ comb7_1)
723 名前:デフォルトの名無しさん mailto:sage [2021/02/05(金) 01:12:53.20 ID:gzN36RyX.net] 読むという目的 可読性の低いコードを、読むことなく却下するという手段 この目的と手段がすぐ入れかわってしまう現象もまた深刻な問題だ
724 名前:デフォルトの名無しさん mailto:sage [2021/02/05(金) 06:11:52.56 ID:5jF91Ui3.net] 速さを求めてnconcみたいなもんだな
725 名前:デフォルトの名無しさん mailto:sage [2021/02/05(金) 19:44:21.42 ID:DBOaHn9B.net] >>713 その遅くて使い物にならない計算を、 可読性をあまり犠牲にしないで爆速にする方法に、 メモ化(memoization)というテクニックがあります。 (その代わり、当然メモリを使います) メモ化関数 memoize が用意されていれば、 n 番目のフィボナッチ数を求める関数 fib は 次のように書けます。 -- メモ化 fib :: Int -> Integer fib = fix (memoize . fib') -- フィボナッチ計算の本体 fib' :: (Int -> Integer) -> Int -> Integer fib' f 0 = 0 fib' f 1 = 1 fib' f n = f (n-1) + f (n-2) メモ化関数を提供するパッケージは色々あります。 また、メモ化の仕組みの基礎や本質を学びたいのなら、 次のごく短いブログ記事がおすすめです。 https://kseo.github.io/posts/2017-01-14-memoization-in-hasekll.html この記事の最後の fibMemo 関数について、 適当な小さな値に適用させたものを 自分でノートに展開してみるといいです。
726 名前:デフォルトの名無しさん mailto:sage [2021/02/05(金) 20:00:27.08 ID:DBOaHn9B.net] >>717 すいません。 肝腎の memoize 関数の定義を書き忘れました。 memoize :: (Int -> a) -> (Int -> a) memoize f = (map f [0 ..] !!) 先に紹介した記事にこれを導く過程や、 より速くより一般化する方法を学びたい人へ向けた URL紹介が載っています。
727 名前:デフォルトの名無しさん mailto:sage [2021/02/06(土) 09:10:00.64 ID:8eeMDweD.net] >>717 解説ありがとうございます やはりメモ化するしかないんだと思います 問題はそれがプログラマが明示的に自分でやらないといけないのか、コンパイラが自分でやってくれるのかの差なんだと思います Haskellは純粋なcall by nameではなく、call by needのシステムの中にメモ化を備えていてプログラマがメモ化するように書いてなくても勝手にメモ化できるものをメモ化してくれるのがすごいとこだと思うんですけど、例えば>>713 の2番目の例で最初見た時「なんでこの定義式でメモ化が効くんだ?」とさっぱりわからなかったのが、実はHaskellのcall by needのシステムをうまく利用してるらしいとわかったのが最初なんです で二重の漸化式だとうまくいかないなと もちろん二重の全炊きでも上手くsuffixの取り方を変えたりすると同様の方法でメモ化できるんですけど、それでは結局「Haskellの機能を利用して明示的にメモ化を指定することなく高速化した」事にはなりません まぁコレはしょうがないんでしょうね どんな計算も常にメモ化して常に同じ評価式を2度扱う事を防いでたらそんなの逆に使い物になりませんからね
728 名前:デフォルトの名無しさん mailto:sage [2021/02/06(土) 20:56:07.58 ID:tGZHMqQF.net] Haskellが「ヤバそう」って偏見だけで敬遠されてるのかなしい… 同級生にも布教したい
729 名前:デフォルトの名無しさん mailto:sage [2021/02/06(土) 21:00:00.51 ID:xuEfQm7n.net] >>720 布教という言葉自体、独善的で押し付けがましく感じられる原因になってると思うよ。 相手がいやがらない程度にhaskellの良さや面白さを伝えてそれでも相手が興味をひかれないなら、それ以上はやめときな。
730 名前:デフォルトの名無しさん mailto:sage [2021/02/06(土) 21:12:54.72 ID:HlAr7yEc.net] >>719 今回の話の本質ではないので、へーそうなんだ、 程度に聞いてくれればいいのですが、 >>713 の2番目の例とは、 f = 0 : 1 : zipWith (+) f (tail f) のことでしょうか。 もしそうなら、これはメモ化ではないですよ。 (このテクニックをなんと呼ぶのかは知りませんが) メモ化というのは簡単にいえば、 関数の同じ引数に対する2度目(以降)の適用に備えて、 その引数に対する1度目の関数の値をその引数とペアにして どこかにメモしておくことです。 ポイントは、2度目以降に備えることではなく、 引数と関数値のペアをメモしておくことです。 それを踏まえて、>>713 の2番目の例において、 では何が関数で、引数と関数値のペアはどこにメモされているか、 考えてみてください。 ただ、言葉の意味は時代と共に変化していくものなので、 今はこれも広義にメモ化と言うことになっているのでしたら、すいません。 私の方が勉強不足です。
731 名前:デフォルトの名無しさん mailto:sage [2021/02/07(日) 08:28:27.99 ID:kgbg5mk/.net] >>717 の方がzipwith使ったものより読みやすくて遥かにいいな こっちの書き方の方がもてはやされてほしいわ
732 名前:デフォルトの名無しさん mailto:sage [2021/02/07(日) 10:58:25.84 ID:nblMEePQ.net] 久しぶりにHaskell(Servant)触ってみたけど 相変わらず呪文のようなテンプレートマクロとかコンパイル通すためだけの幽霊型とか表に出てきているのね こういうの後ろに隠した実装がほちい(・ัω・ั)
733 名前:デフォルトの名無しさん [2021/02/07(日) 21:10:43.40 ID:B3cRggdVq] 怒る・叱る文化は、安月給&長時間労働の証 https://www.youtube.com/watch?v=-FZ-W08t9vM&t=173s 勉強しない社員★仕事のための投資をしない人たち https://www.youtube.com/watch?v=Zg6N7a_h8AE バカが起業したんです★バカが社長になる過程 https://www.youtube.com/watch?v=WT3pvyhpazk 時給10倍差は勉強と努力だけで差がつく★最大100倍差! https://www.youtube.com/watch?v=AHZjacip9Y4 ドリームキラー★夢の実現を応援する人、阻止する人 https://www.youtube.com/watch?v=ZoVXtIxhqTU 年収1億円は「できっこない」をやり遂げた人★10万人、銀の盾来た! https://www.youtube.com/watch?v=3t9nQgcIzLw
734 名前:デフォルトの名無しさん mailto:sage [2021/02/07(日) 19:10:10.31 ID:Ae+USThM.net] >>724 試しに作ってみればいいのでは? そういう気に入らない幽霊型を とりあえず1つだけ後ろに隠してみて、 使いやすいか試してみればいいと思う。 良さそうなら、ここや GitHub で提案するとか。
735 名前:デフォルトの名無しさん mailto:sage [2021/02/07(日) 21:05:48.19 ID:kgbg5mk/.net] Servant辛いから是非お願いしたい
736 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 03:22:56.40 ID:lr3qr0Kv.net] >>708 レスが遅くなりましてすいません。 xの定義にx自身を参照していますが、それだけでは 再帰的に定義されているとは言えないということですか。 例えば次の関数 f は再帰的に定義していると皆が言います。 f n = if n == 0 then 1 else n * f (n-1) これと >>706 の x とは何が違うのでしょうか。
737 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 07:06:31.27 ID:aZaTrcsy.net] >>728 fix x はxの定義じゃなくてfixの定義では
738 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 09:04:48.35 ID:THE6D9/g.net] >>729 fix定義の中でlet節を使って定義されているxの話です。
739 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 12:31:08.86 ID:hFpKnaPX.net] >>717 リスト使ったメモ化の理解にはいいんですけど、その例も実は遅いんですよね。!!がO(n)なので。 module Main where import Data.Function import qualified Data.Vector as V main = do let memo = fibMyMemo 50000 print $memo 50000 print $fibMemo 50000 fibMyMemo l = fib where fib = ((V.map f $ V.enumFromN 0 (l + 1)) V.!) f 0 = 0 :: Integer f 1 = 1 f n = fib (n -1) + fib (n -2) memoize f = (map f [0 ..] !!) fib f 0 = 0 fib f 1 = 1 fib f n = f (n - 1) + f (n - 2) fibMemo = fix (memoize . fib)
740 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 18:33:31.66 ID:USGkiU7i.net] >>728 マジョリティとマイノリティの違いとか、合法とグレーの違いのようなものだと思えばいいだろ 再帰的な関数と再帰的な型はよく知られている 一方、関数でも型でもないケースは未知のウイルスのようなもので 既存のものと同じだとすぐ決めつけるのは判断が早過ぎる極論
741 名前:デフォルトの名無しさん mailto:sage [2021/02/08(月) 20:09:46.17 ID:xtdfQPSv.net] >>731 そうですね。 なので、実際は Trie 木でメモする MemoTrie が効率良いと思います。
742 名前:デフォルトの名無しさん [2021/02/09(火) 17:58:55.95 ID:czfvLw+x2] アスペルガー症候群と高機能自閉症 「反復運動」と「限定された物事へのこだわり・興味」 3つの診断基準 @人とのやり取り、関わりが難しい(社会性の障害) Aコミュニケーションがとりにくい(コミュニケーションの障害) B興味・行動の偏り、こだわり(限定的な行動・興味・反復行動) ASD(自閉スペクトラム症、アスペルガー症候群)の症状 細部にとらわれてしまい、最後まで物事を遂行することが出来ない 視線があいにくく、表情が乏しい 切り替えが苦手、決まったパターンと違うと癇癪を起こす、集団での活動・遊びが苦手。
743 名前:デフォルトの名無しさん mailto:sage [2021/02/10(水) 06:55:43.73 ID:w+SbAYAx.net] >>732 すいません、結局のところ、どういう事でしょう?
744 名前:デフォルトの名無しさん mailto:sage [2021/02/10(水) 10:35:38.44 ID:tXb64EJq.net] 法律や善悪の判断の正しさを疑うのと同じレベルの懐疑的な思考が 数学やデバッグにも必要ということかな
745 名前:デフォルトの名無しさん mailto:sage [2021/02/10(水) 11:17:11.88 ID:tXb64EJq.net] 静的型は最強とかガベコレは最強とかいう考えが 疑われるようになったのは半分ぐらいHaskellが原因だよね
746 名前:デフォルトの名無しさん mailto:sage [2021/02/10(水) 13:30:33.82 ID:em7GM66H.net] >>732 ←こいつまだいたのか 気持ち悪すぎる
747 名前:デフォルトの名無しさん mailto:sage [2021/02/10(水) 14:18:45.17 ID:tXb64EJq.net] ここは無料だしこんなもんだろ 良いものはみんな課金される
748 名前:デフォルトの名無しさん mailto:sage [2021/02/11(木) 14:43:11.06 ID:/UgD5Hp7.net] 地獄の沙汰も金次第 だが天国への言及はない
749 名前:デフォルトの名無しさん mailto:sage [2021/02/11(木) 16:56:32.70 ID:zBw+qxbZ.net] ねえ、購入厨 ひょっとしてHaskellは、きみが同じ地獄を繰り返す毎に 強力なフリーソフトになっていったんじゃないのかい
750 名前:デフォルトの名無しさん mailto:sage [2021/02/13(土) 21:17:16.21 ID:kqsb0S1y.net] 悪役キャラには著作権等のコンプライアンスを意識させると邪気が抜けてしまう 豆知識
751 名前:デフォルトの名無しさん mailto:sage [2021/02/14(日) 18:40:01.75 .net] なぜ Haskell スレはワードサラダ bot に狙われてしまうのか
752 名前:デフォルトの名無しさん mailto:sage [2021/02/14(日) 20:59:33.34 ID:2j5v2BhK.net] >>743 ネットの差別発言を排除する努力すらやらない人がいるから ワードサラダとやらを排除する努力なんて誰もやらないのは当たり前だぞ こんな簡単なことがなぜ理解できないんだ
753 名前:デフォルトの名無しさん mailto:sage [2021/02/14(日) 21:27:29.30 ID:A1oxlP1a.net] 731はワードサラダなレスうぜぇなぁくらいの意味しかなくワードサラダなレスが存在してしまう理由を実際に疑問に思っているわけではないという簡単なことが何故わからないのか
754 名前:デフォルトの名無しさん mailto:sage [2021/02/14(日) 21:49:22.17 ID:2j5v2BhK.net] 731は、うぜぇなぁ以外何も考えてなかったというのか それは差別意識しかない絶対悪じゃないか
755 名前:デフォルトの名無しさん mailto:sage [2021/02/15(月) 01:08:13.78 ID:Qrz9kKC+.net] もっと危機感を持ったほうがいいよ 母国語の特徴までネチネチいじられたら外国語はこわくて使えないだろう 英語ができないとプログラミングもできない
756 名前:デフォルトの名無しさん mailto:sage [2021/02/15(月) 17:23:26.09 ID:Mv5LolEs.net] なんかこのスレ会話が噛み合わないよな >>744 ←こいつとか明らかに頭おかしいし こういう人外化け物がうじゃうじゃいるから「特技はコミュニケーション能力です」みたいなゴミ文系が社会で調子に乗り始めるんだろうな
757 名前:デフォルトの名無しさん mailto:sage [2021/02/15(月) 18:24:29.13 ID:Qrz9kKC+.net] コミュ力の悪用を止める方法で一番使えそうなのは制限時間を無くすことだ 5秒で答えさせるような問題でも時間のルールを無視してしまえば そのゴミ文系ってやつの能力を擬似的にコピーできる
758 名前:デフォルトの名無しさん mailto:sage [2021/02/15(月) 19:02:15.47 ID:3zpQr6lX.net] Haskellの話は?
759 名前:デフォルトの名無しさん mailto:sage [2021/02/15(月) 20:58:35.44 ID:Qrz9kKC+.net] 最小不動点を定義する半順序の定義がない それと「再帰」の定義がない
760 名前:デフォルトの名無しさん mailto:sage [2021/02/16(火) 10:45:42.61 ID:AZNZAZhP.net] >>750 こういう話? ttps://i.imgur.com/oKvfp6x.png
761 名前:デフォルトの名無しさん mailto:sage [2021/02/16(火) 12:56:19.11 ID:VICwQMLs.net] 質問なんですが, https://levelup.gitconnected.com/functional-dynamic-programming-with-haskell-top-down-and-bottom-up-7ccade222337 の一番上のコード内23-25行目の iMinusOne <- cdRecursiveTD (i-1) stArr iMinusTwo <- cdRecursiveTD (i-2) stArr writeArray stArr i ( (i-1) * ( iMinusOne + iMinusTwo ) ) の部分を添え字使って for j = 1 to 2 xs !! j <- cdRecursiveTD (i-j) stArr writeArray stArr i ( (i-1) * ( sum xs ) ) みたいに書く方法ってありませんかね?
762 名前:デフォルトの名無しさん mailto:sage [2021/02/16(火) 15:13:16.20 ID:VICwQMLs.net] すみません自己解決しました 一応結果貼っておきます cdRecursiveTD i stArr = do ____v <- readArray stArr i ____when (v == -1) $ do ______xsm <- newSTRef [] ______forM_ [1,2] $ \j -> do ________x <- cdRecursiveTD (i-j) stArr ________modifySTRef xsm (x:) ______xs <- readSTRef xsm ______writeArray stArr i ( (i-1) * ( sum xs ) ) ____readArray stArr i
763 名前:デフォルトの名無しさん mailto:sage [2021/02/16(火) 15:27:24.80 ID:twhDC3NA.net] xs <- mapM (\j -> cdRecursiveTD (i - j) stArr) [1 .. 2] writeArray stArr i ((i - 1) * sum xs) これでよくないですかー?
764 名前:デフォルトの名無しさん mailto:sage [2021/02/16(火) 15:32:43.34 ID:VICwQMLs.net] >>755 そっちの方が遥に良いですね… ありがとうございます
765 名前:デフォルトの名無しさん mailto:sage [2021/02/17(水) 14:02:08.57 ID:YPZ4jTJ4.net] map f [1,1,1,2]のように重複の多いリストがあったら fの実装を変える勢力とリストの構造を変える勢力の争いをどうやって解決できるか気になる
766 名前:デフォルトの名無しさん mailto:sage [2021/02/17(水) 16:20:43.74 ID:mAFPwKeZ.net] 一回Set型にしてからListに戻す
767 名前:デフォルトの名無しさん mailto:sage [2021/02/17(水) 16:22:11.25 ID:mAFPwKeZ.net] もちろんリストの要素の個数減って良い場合の話だけど
768 名前:デフォルトの名無しさん mailto:sage [2021/02/17(水) 22:40:59.85 ID:0SJ3Yct4.net] >>757 具体的な問題状況(例)が示されなければ、次のような何にでも当てはまる 至極当たり前のつまらない回答しかできないと思うが。 目的、開発リソース(時間や設備、資料、費用など)、 開発者の能力やモチベーション、メンテの容易さなどを、 優先順位を考慮したうえで出来るだけ客観的に評価し決定する。 争うということは、優先順位や評価基準が定まっていないということなので、 まずはそれらを話し合って、あるいは上の立場の者がバシッと決める。
769 名前:デフォルトの名無しさん mailto:sage [2021/02/18(木) 09:29:03.36 ID:8Wc99cSo.net] なんかしょうもない話なんですけどウチの環境で次が通ります test x = case x of _ | odd x -> 1 oyherwise -> 0 main = do print $ test 123 print $ test 456 なんか笑ってしまいました
770 名前:デフォルトの名無しさん mailto:sage [2021/02/18(木) 09:31:00.46 ID:8Wc99cSo.net] あ、イヤ違う 勘違いでした すいません