関数型プログラミング言語Haskell Part31©2ch.net

■ このスレッドは過去ログ倉庫に格納されています
2017/09/27(水) 02:33:08.70ID:2XAqPuH2
関数型プログラミング言語 Haskell について語るスレです。

haskell.org (公式サイト)
https://www.haskell.org/

前スレ
関数型プログラミング言語Haskell Part30
http://mevius.2ch.net/test/read.cgi/tech/1484491434/
2017/10/30(月) 11:28:25.84ID:WTE/ZW3E
>>169
ごめん、ダメだな。

素直にシードフィルみたいに辿っていくしかないか。
2017/10/30(月) 11:57:14.99ID:I1PPVtSx
最適化O2からなの忘れてたすまん
2017/10/30(月) 12:01:00.21ID:WTE/ZW3E
>>160
Haskell が得意なアルゴリズムは分割統治なので、
できるだけ分割統治で解けないか考える、
というのが一般的なアプローチ。

だけど、この問題はそれでは解けそうもないので、
他の命令型言語と同じアルゴリズムを使うしかないと思う。

で、これは一筆書き問題なので、
「連結グラフがオイラー路かまたは準オイラー路なら一筆書き可能」
という定理を利用することになる。

オイラー路や準オイラー路の判定は簡単。

肝は連結グラフの判定だけど、これはもう素直に調べるしかない。
普通ならグラフ用ライブラリを使うところだけど、
競技ならまず使えないだろうから、2次元配列を使ってグラフを表現する。
そして頂点をひとつ決めて、そこから全頂点を辿れるか調べる。

これしかないね。
Haskellにはとことん向かない問題だと思う。
173デフォルトの名無しさん
垢版 |
2017/10/30(月) 12:13:21.53ID:/4xzRH5O
Haskellわからんからわからんのだがこれとか簡単にかけてそうなんだがそうでもないのか?
https://yukicoder.me/submissions/213035
2017/10/30(月) 12:24:13.36ID:oL0091Lz
>>173
連結性の判定を忘れてた
175デフォルトの名無しさん
垢版 |
2017/10/30(月) 12:25:22.45ID:/4xzRH5O
>>174
よく見たらWrong Answerだったわ...orz
176160
垢版 |
2017/10/30(月) 20:27:20.42ID:kEApsxXD
>>165-175
助言ありがとうございました
Haskellは分割統治が得意、連結判定苦手で覚えます
2017/10/30(月) 22:41:45.81ID:bEDc9q0a
連結判定だけじゃなくてグラフがらみは総じて苦手じゃないかな
2017/10/31(火) 01:03:17.65ID:hkKKSLGp
コンパイラはグラフ簡約するのに言語はグラフ苦手なのかよお
2017/10/31(火) 01:46:52.15ID:HrVASABH
つうか制約のない連結性の判定を深さ優先探索でするのは別にHaskellのせいじゃないだろ
2017/10/31(火) 03:22:06.20ID:mBYeMGb0
グラフ苦手って競技プログラミングで使う場合のみやろ?普段使う分にはグラフライブラリに突っ込めばいいだけやし気にする必要無いやで!
2017/10/31(火) 08:27:49.90ID:v6NvB8KL
ライブラリでも、計算量は多くなるよね?
2017/10/31(火) 08:33:52.06ID:ipWwIy6g
わざわざ車輪の再発明させる競プロってなんなん
2017/10/31(火) 08:44:38.36ID:DbaXyY3l
Data.Array.(!) や Data.Vector.(!) って O(1) でアクセスできるんですか?
純粋な関数型言語でそんなこと可能なのですか?
2017/10/31(火) 08:50:21.95ID:DbaXyY3l
>>182
その方が面白いからだと思いますよ。
コードゴルフとかと同じですよ。
制約があった方が燃えます。
2017/10/31(火) 10:02:54.23ID:HrVASABH
>>183
>Data.Array.(!) や Data.Vector.(!) って O(1) でアクセスできるんですか?
>純粋な関数型言語でそんなこと可能なのですか?

読む分にはO(1)に決まってる
そもそもData.Vectorのドキュメントに様々な関数の計算量が書いてあるだろ
2017/10/31(火) 10:40:05.74ID:DbaXyY3l
>>185
要素数に依存しない計算量で構造から読み取るなんて、
純粋な関数だけでどうやって実現するの?
不思議すぎない?
2017/10/31(火) 11:15:03.94ID:HrVASABH
はあ?
インデクスからメモリ上の位置(たとえばポインタ)へのO(1)な関数があればいいだけだろ
通常の配列もハッシュも変わらん
2017/10/31(火) 11:25:52.68ID:u1zcRbeB
ライブラリとして提供されてるからそうであって、
Haskellの構文としては書けないって話では?
189デフォルトの名無しさん
垢版 |
2017/10/31(火) 11:28:55.70ID:0GSWnPMN
>>187
キッシヨ
190デフォルトの名無しさん
垢版 |
2017/10/31(火) 11:31:18.73ID:0GSWnPMN
ミスった
キスしよ、な
2017/10/31(火) 11:33:38.62ID:DbaXyY3l
>>187
そのO(1)な関数は純粋関数型でどうやって実現してるの?
俺はすげー不思議、という話だよ。
2017/10/31(火) 11:36:03.56ID:K+wdnCfv
純粋データ型のオブジェクトはすべて構築物
(つまり既存のオブジェクトから構築されたもの)
という視点を持たないとこの手の話は一生理解できんと思う
2017/10/31(火) 11:46:17.59ID:DbaXyY3l
>>192
このあたり、「純粋関数型データ構造」って本で勉強できる?
それともあの本は関係ない?
2017/10/31(火) 13:07:49.38ID:xZzZlui7
1 = \x _ _ ... -> x
2 = \_ x _ ... -> x
3 = \_ _ x ... -> x
~
という自然数を定義すれば
\i -> i a b c ...
で参照O(1)な配列の出来上がり
2017/10/31(火) 13:20:29.54ID:DbaXyY3l
>>194
それじゃあ、Data.Vector みたいに動的に生成できないでしょ。

ワザととぼけてるの?
それとも話の流れ分かってない?
2017/10/31(火) 13:30:02.62ID:xZzZlui7
>>195
\x y z ... -> \i -> i x y z ...
2017/10/31(火) 13:43:09.29ID:xihCdoaS
C言語で実装してラップしてんじゃないの(知らんけど)
2017/10/31(火) 13:47:50.97ID:DbaXyY3l
>>196
すげーおまえ頭いいなって思ったが、すまん、
こっちの頭が悪すぎた、まだ何となくしか理解できん。

たとえば、リストから一次元配列を作る関数をつくってくれないか?

ずうずうしいと思ったら、ヒントだけでも。

fromList :: [a] -> 配列型 a
fromList xs = ムニャムニャ
2017/10/31(火) 15:36:16.62ID:xihCdoaS
C言語で実装してラップしてんじゃないの(知らんけど)
2017/10/31(火) 15:50:28.40ID:xZzZlui7
>>198
いやチャーチエンコーディングのパクリだよ
fromList xs = foldl ($) (\x y z ... -> \i -> x y z ...) xs
実際は型チェックが通らないからアキュームレーターの関数を
data Func a b = Res b | Func (a -> Func a b)
みたいな型で作って結果をパターンマッチすればいい
2017/10/31(火) 16:16:10.45ID:DbaXyY3l
>>200
ありがと

あかん、頭の中で考えてても理解できん、
と言うかスッキリしない。
家に帰ったらじっくり勉強してみるよ。
2017/10/31(火) 18:15:23.97ID:gU/sNGWK
競プロで使えるグラフライブラリにData.Graphってのあるのな

Data.Graph
https://hackage.haskell.org/package/containers-0.5.10.2/docs/Data-Graph.html
2017/10/31(火) 19:08:38.44ID:1toVIYFj
>>202
上の問題でverticesとreachableの長さを比較すればと思ったら
verticesは辺の無い頂点も列挙する仕様だったわ
まあGraphの中身はリストの配列だから自分で数えればいいんだけど
2017/10/31(火) 21:49:16.80ID:uNFhbghr
関数合成ってhoge.piyoよかhoge . piyoの方が可読性高い?
2017/11/01(水) 00:06:04.05ID:viv8LMSD
>>204
スペース無しドットはモジュールの名前空間の表現に使うから
関数合成は後者で書く方がいいよ
モジュール名は大文字で関数名は小文字だからコンパイラは間違えないけど
2017/11/01(水) 00:26:27.90ID:llNAjsKg
hackageのソースコード見ても合成のドットは離して書いてるの多いね
2017/11/01(水) 00:27:10.19ID:WlWR964+
>>205
やっぱりそうですか
ありがとうございます
2017/11/01(水) 01:06:06.52ID:Fgn1cTLB
人間も間違えねえよってつっかかってくる人昔みかけた
そういう人が出たら、宗教戦争やめろっていうつもりだったのに
2017/11/01(水) 07:53:11.67ID:DzcCU70V
「大文字と小文字を間違えない」の主語は何かの戦争か
そもそも主語を書く必要があるのか
2017/11/01(水) 09:43:47.82ID:55me074h
データコンストラクタも大文字なので(ry
2017/11/01(水) 11:37:03.55ID:DzcCU70V
最初の文字が大文字やドットなら特別な意味がありそう
最初ってどこなのかは正規表現で定義すれば間違いなさそう
2017/11/04(土) 23:17:33.32ID:GxslH7p8
リスト内包表記がdo表記に一対一に対応するのは知っていますが、
言語拡張 TransformListComp によって拡張されたリスト内包表記も、
一対一に対応するdo表記があるのでしょうか。

then group by e using f の働きがどのような仕組みなのかよく分からないので、
対応するdo表記を調べて理解を深めたいです。
2017/11/05(日) 08:59:13.86ID:BXN9Zljm
>>212
>対応するdo表記を調べて理解を深めたいです。

どうぞそうなさって結果をスレにてご報告ください。
2017/11/05(日) 11:02:14.73ID:33a+kqna
>>213
いろいろ実験したり、GHCのユーザーガイドを読んだりしたところ、
then group by p using f の働きが理解できました。

しかし、結局のところ対応するdo表記は分かりませんでした。
そんなものはもともと無いのかもしれません。
もしかしたらCoreを出力してみると何か分かるかもしれませんが、
自分の中ではもう問題が解決しているので、そこまで調べるモチベーションがありません。
なので、ここでその結果を報告することはできません。

代わりに、then group by p using f がどのような働きになっているのか、
私の知見だけでも述べた方が良いでしょうか。
2017/11/05(日) 13:47:42.35ID:iHS/FHvi
知見は歓迎です
2017/11/05(日) 14:29:15.46ID:g7Wivisu
https://downloads.haskell.org/~ghc/7.8.3/docs/html/users_guide/syntax-extns.html#monad-comprehensions
> D[ e | Q then group by b using f, R ] = f (\Qv -> b) D[ Qv | Q ] >>= \ys ->
> case (fmap selQv1 ys, ..., fmap selQvn ys) of
> Qv -> D[ e | R ]
> where Qv is the tuple of variables bound by Q (and used subsequently)
> selQvi is a selector mapping Qv to the ith component of Qv
別にモナドで定義されてるからdoで定義してもいいけど
Qvから要素を取り出す方法がアドホックにしか書けないから
doを使わないにしろ一対一で対応するようには書けない
2017/11/05(日) 18:08:38.19ID:Rt4/SB7E
Haskellの表記を楽にする6つのghc拡張 - Qiita
https://qiita.com/philopon/items/b812e43128654245e42d
2017/11/05(日) 23:15:17.53ID:s0bBqtdw
>>217
MultiWayIfとBinaryLiterals以外は可読性落ちとるやないかーい
2017/11/05(日) 23:28:42.70ID:33a+kqna
>>212 です。

then group by p using f の働きはいろいろ不思議な部分があるのですが、
すべての疑問は、then group by p using f で使う関数 f :: (a -> t) -> [a] -> [[a]] の第1引数は
どのような関数が渡されるのか、ということに集約されました。
(それが分かって初めて、これは then f by p の f でも同じだと気づきましたが、
こちらでは理解につまづかない程度の簡単な例しか扱っていなかったので)

この関数 f は、then group by p using f が現れるより左にある全てのバインダを要素に持つ組から p への関数
と考えれば納得がいきました。

たとえば、
[ (x, y) | x <- [1,2,1], y <- "ok", then group by x using groupWith]
ですと、then より左のバインダを要素に持つ組というのは、つまり
<1, o>, <1, k>, <2, o>, <2, k>, <1, o>, <1, k> といった組です。
(実際に内部で使われている実際のデータ型は分かりません)

このような組から x への関数なので、
g <1, o> = 1
g <1, k> = 1
g <2, o> = 2
g <2, k> = 2
という関数です。
このような関数 g が groupWith 関数の第1引数に渡されると考えると辻褄が合いました。
2017/11/13(月) 22:38:59.83ID:GpiHsSLN
haskell始めてみたいんだけどまだプログラミング能力があまりないので不安
他の言語をどれくらい書けるようにしておくべき?
2017/11/13(月) 23:15:58.10ID:IehbHsjb
むしろ手続き型言語に慣れ親しんだ脳みそだと関数型は取っ付きにくいから
いきなりHaskellでいいと思うよ
2017/11/13(月) 23:27:39.67ID:ZUv/XWe7
>>221
Masterminds of Programming という本で Haskell 委員会のひとりが、
他言語をちゃんとできるヤツはHaskellも上手く使える、という趣旨のことを言ってた。
2017/11/13(月) 23:30:10.81ID:ZUv/XWe7
>>221
それどころか、いきなりHaskellをやるのはお勧めしない感じだった。
224デフォルトの名無しさん
垢版 |
2017/11/13(月) 23:30:57.19ID:PxhTPMZi
>>222
「ちゃんと出来る」の意味が、常人と違う予感。
2017/11/13(月) 23:42:04.93ID:dMdke9KA
いきなりHaskellの難点はどのHaskell入門書籍やサイトも基本的なプログラミング知識を前提としちゃってるとこかな
変数とか関数とかリストとかマップとか
でもHaskellというか関数型パラダイムにできるだけ早い時期から触れとくのは良いことだと思う
2017/11/14(火) 00:36:12.17ID:XSI09cgL
>>220

『プログラミングの基礎』浅井健一

でOCamlやってからHaskellに逝くのが一番簡単な導入
2017/11/14(火) 00:42:09.25ID:Meoq/IF/
SICP読んでからhaskellやるのは大丈夫?
2017/11/14(火) 02:30:14.88ID:RezF4qhu
Haskellは日本語どころか
英語でググっても答えが見つからない問題にぶち当たる率が
他のメジャーな言語と比べると高すぎるから初学者向きじゃないよ

もくもく会に参加したり、Stack Overflowで質問したりと
双方向的な方法を挟まないと一定以上に到達するのは難しい
2017/11/14(火) 11:28:30.93ID:eZNGHHYs
問題自体が難しい
だから答えが見つからない
と解釈するのが自然

問題自体をよく見ようとせず、SEOや脳味噌のことを考えるのは的外れだと思う
2017/11/14(火) 19:55:37.30ID:0CBPSjnu
ocamlの元のmlで挫折しそうになった。
f#がたのしい
2017/11/14(火) 20:17:46.83ID:WUG8DCiI
例えばC言語の楽しさを1とすると
haskell,ocaml,f#の楽しさはどれぐらい?
2017/11/14(火) 21:11:59.47ID:eZNGHHYs
F#はC#の知識を前提とすることを許可されている感がある
箸の上げ下ろしどころか知識を得るのにも許可を必要とする異常な環境に適応したのがF#
2017/11/14(火) 22:22:03.84ID:0CBPSjnu
f#はなんかこう昔懐かしbasicの関数型言語版のよう
な気がする。
2017/11/14(火) 22:22:45.27ID:0CBPSjnu
haskell構文がやだ。
2017/11/14(火) 22:58:23.51ID:LvvrWEBo
>>234
たとえば、どんな構文が?

遅延評価とか参照透過性とか厳密な型付けとか、そういうのを嫌う人はいっぱいいたけど、
構文が嫌って人には初めて出会った。
2017/11/14(火) 22:59:13.88ID:wshk46M/
F#固有のライブラリ使ったことないな
構文的にC#よりF#楽
あとはHaskell並みの肩推論あれば文句ないんだけど
Haskellは遅延評価使いどころを見つけづらい
2017/11/14(火) 23:31:10.95ID:lH5WJrT0
結構凝ってるみたいっすねえ
2017/11/15(水) 01:49:26.34ID:9iJNvTMA
むしろ構文が好きだわ
限りなく不要な物は省く的な
2017/11/15(水) 07:22:37.14ID:1MOdQV57
インデントルールにたまにハマるくらいかな
一応ブレース&セミコロン方式でも書けるようだが
2017/11/15(水) 12:36:08.57ID:Lu+q1695
合成関数を左から右に書きたい
何か数学でそんな書き方もあったと思うんだけど忘れた
2017/11/15(水) 17:52:48.58ID:C1PNunQ6
Control.Arrow の (>>>) 演算子使えばいい
($) の引数入れ替えたヴァージョンなら Data.Function の (&) 演算子
2017/11/15(水) 17:55:11.80ID:C1PNunQ6
>>239
>一応ブレース&セミコロン方式でも書けるようだが

標準的なコーディングスタイルだと使わないからなあ……
コード生成のときなんかには便利だけど
2017/11/15(水) 21:31:38.92ID:ouxrorYh
Preludeに引数を入れ替えるというだけの関数なかったっけ?
マニアック過ぎて忘れてしまった
2017/11/15(水) 22:05:39.40ID:C1PNunQ6
つ flip

全然マニアックじゃないよ……
245デフォルトの名無しさん
垢版 |
2017/11/16(木) 19:05:18.93ID:U25znXQF
Haskellが競プロで得意なグラフ問題がatcoderでマラソン形式で出題されているらしい
2017/11/16(木) 20:02:11.38ID:fiTPZdVA
誰もhaskell使ってないでしょ
247デフォルトの名無しさん
垢版 |
2017/11/16(木) 20:10:09.25ID:sSGm4ReW
使うものじゃないからな。
2017/11/16(木) 20:21:11.26ID:F5ZZYHwp
競プロでHaskell使ってた人は皆Rustに移ったイメージ
2017/11/16(木) 20:28:57.17ID:BHFP68Bt
競プロは普通に手続き型かつ破壊的の方がいいもんな
入力範囲も固定だし、Haskellで挑む理由がない
2017/11/16(木) 21:32:29.59ID:F5ZZYHwp
関数型っぽく書くと実装が一瞬で完了する簡単な問題が結構あったりはする
2017/11/16(木) 21:43:12.74ID:wcx5gPy1
競プロより Project Euler で付けた力の方が将来の糧になりそう
2017/11/16(木) 22:35:40.89ID:1hTLcaK1
Haskellはアルゴリズムをうまくfold系で書ければ
融合則とかで綺麗さと速度を両立できる感じになるけど
うまく書けないとSTRefとか使うことになって
なぜHaskellやってるんだって気分になる
2017/11/17(金) 00:37:00.18ID:ehxZncBr
ストリーム処理的にしか使ってない
2017/11/17(金) 00:38:56.41ID:ehxZncBr
ストリーム処理的にしか使ってない
https://ideone.com/kYgQxV
2017/11/17(金) 11:21:31.36ID:7fJDQyWy
>>252
fold系には合わない計算があるのは分かる。

でも、なぜそれでSTRefを使うことになるのかが分からない。
2017/11/17(金) 12:39:19.61ID:edPG1sGH
別にIORefやSTRefを使ったっていいじゃない
FFIだってポインターだってあるじゃない
ただしStateモナド、テメーはダメだ
257デフォルトの名無しさん
垢版 |
2017/11/17(金) 16:36:27.24ID:FedOcmK4
よく知らないけど
カーソル的なクラスと同じように使えるんじゃない?Stateって
Stateモナドに入るのがインスタンス生成で>>=がメソッドコール
2017/11/17(金) 17:56:56.51ID:oGefn9Ej
1 s -> (a, s)
2 s -> (a -> s -> s) -> s
3 (a -> s -> s) -> s -> s
4 (a -> s -> s) -> s -> [a] -> s

1がStateで4がfoldr
2017/11/17(金) 20:49:15.19ID:M/sHB851
Haskellって他人のコード読むと

▲ a b = □ . ○ $ map ■ $ (△ a) $ ▼ $ ◎ b []
 where
  ◎ b xs = 〜長い処理〜

こんなんばかりで脳がパンクするんだが
2017/11/17(金) 20:52:24.67ID:FaJpeIXU
むしろ他人のコードでも割とサクサク読めるのがHaskellのメリットじゃね?
2017/11/17(金) 22:00:31.45ID:Tih5fc0e
>>259
せっかく参照透過性が保たれているのだから、自分が読みやすいように、
でも式の意味は変えないように変形すればいい。

複雑なコードに出会って、それでも理解したいという欲求があるのなら、
取りあえず脳がパンクしない程度の小片にまで分解してみればいいんじゃないか。
2017/11/17(金) 23:01:40.13ID:5gG4LJO3
なるほど処理を理解しきっていなくても
他人のコードを自分が読みやすく変形出来るのが参照透過性のメリットなのね。
その発想はなかったから今度から試してみる。
2017/11/18(土) 00:48:05.98ID:Na4dLuAE
>>255
foldに乗らない処理ってのが
要は愚直に再帰で書いてるループ計算で、
破壊的更新をしないとものすごいGCが走ってつらいということがあった
(データ構造にもっと工夫の余地があったとは思う)
2017/11/18(土) 02:53:34.88ID:/UaXWK/X
実際再帰って最終手段だよね。
入門者向けには基本みたいに言われている謎。
2017/11/18(土) 08:54:42.51ID:6/fTmZe2
言うほど最終手段ではないし基本なのは事実
2017/11/18(土) 12:58:42.16ID:TxAwv536
Haskellってループないんじゃなかったけ
再帰なしでどうやって組むんじゃ
2017/11/18(土) 13:13:54.77ID:qwbMNygr
>>266
リストで言うならmapとかfoldlあたりで対応できるならそれを使えばいい
ユーザー定義の再帰関数は自由度は高いけど終了条件を見落とす可能性もあるし、場合によっては末尾再帰やら正格評価やらも気にせんといかん
必要としている仕事より強く自由度が高い関数や型をあまり使わない方がいいのは他言語と同じ
2017/11/18(土) 13:17:08.17ID:6/fTmZe2
直近で書いた120行程度で関数定義25個を含んだコードを見返したが、確かに再帰は一箇所もなかった。
2017/11/18(土) 13:21:49.25ID:IKdiOjx3
要するに集合演算があるから繰り返す必要がないということか
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況