関数型プログラミング言語 Haskell について語るスレです。
Haskell Language(公式サイト)
https://www.haskell.org/
日本Haskellユーザーグループ - Haskell-jp
https://haskell.jp/
前スレ
関数型プログラミング言語Haskell Part32
https://mevius.5ch.net/test/read.cgi/tech/1548720347/
探検
関数型プログラミング言語Haskell Part33
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
2020/02/10(月) 18:17:36.49ID:L6eYQqyh479デフォルトの名無しさん
2020/09/07(月) 11:55:03.70ID:xmFuETjj 純粋に興味からです
480デフォルトの名無しさん
2020/09/07(月) 17:09:40.33ID:6+huFxV7 >>465
マクレーンの圏論とか読んでも果てしなく遠回りするだけだぞ。
マクレーンの圏論とか読んでも果てしなく遠回りするだけだぞ。
481デフォルトの名無しさん
2020/09/07(月) 17:57:43.88ID:kXMphwO9 >>480
ベーシック圏論はどうですか?
ベーシック圏論はどうですか?
482デフォルトの名無しさん
2020/09/07(月) 18:10:28.73ID:oaoIrH3d haskellのモナド理解するだけなら圏論いらないからね
ベーシック圏論は内容を限定して敷居の低い例を使っているので相対的には
読みやすいけど、基礎的な数学の知識がないと例が理解の助けにならないのは同じ
ベーシック圏論は内容を限定して敷居の低い例を使っているので相対的には
読みやすいけど、基礎的な数学の知識がないと例が理解の助けにならないのは同じ
483デフォルトの名無しさん
2020/09/07(月) 20:28:07.77ID:xmFuETjj 関手って圏が持つ「対象と射」同志の関連付けのことだよね?
なぜfmap関数を定義すると関手を実装したことになるの?
なぜfmap関数を定義すると関手を実装したことになるの?
484デフォルトの名無しさん
2020/09/07(月) 21:15:30.28ID:3sLeGs6G fmapという名前が変
関手は射と見なせる
関手は射と見なせる
485デフォルトの名無しさん
2020/09/09(水) 09:53:26.80ID:TuvEFz+K 勝俣「シャー!」
486デフォルトの名無しさん
2020/09/09(水) 10:39:29.87ID:o85d1us6 圏の圏な
487デフォルトの名無しさん
2020/09/09(水) 11:37:10.69ID:sfIbn56V 圏論いらずで、モナド理解するのにどうすりゃいいの?
488デフォルトの名無しさん
2020/09/09(水) 12:18:16.37ID:/Y+BdKRx do記法が使えるようになる
モナド=>モナド則を満たす=>do記法はモナド則の別バージョン
結局のところ、モナドはdo記法を作りたかった。よって、先頭の話になる。
モナド=>モナド則を満たす=>do記法はモナド則の別バージョン
結局のところ、モナドはdo記法を作りたかった。よって、先頭の話になる。
489デフォルトの名無しさん
2020/09/09(水) 12:43:31.80ID:/Y+BdKRx ちょっと嘘だな
488は既にあるモナドを使う場合の話で
自分でモナドを作ってみたいのなら
モナド則を満たしていることの確認が必要
ってことで、モナド則の勉強も必要
個人的にモナドが一番分かり易かったのは、↓かな
サルでもわかるIOモナド@-B
http://hot-heart-cool-mind.seesaa.net/article/393131366.html
488は既にあるモナドを使う場合の話で
自分でモナドを作ってみたいのなら
モナド則を満たしていることの確認が必要
ってことで、モナド則の勉強も必要
個人的にモナドが一番分かり易かったのは、↓かな
サルでもわかるIOモナド@-B
http://hot-heart-cool-mind.seesaa.net/article/393131366.html
490デフォルトの名無しさん
2020/09/09(水) 12:59:11.96ID:7PwBIIdR モナドというのが何なのか知らないのですが、モナドが何か分かっていないとモナドは使えないものなんですか?
491デフォルトの名無しさん
2020/09/09(水) 13:33:56.84ID:Ss6OMKhc Haskellで出てくる演算子の読み方一覧ってないですか?
492デフォルトの名無しさん
2020/09/09(水) 18:46:46.75ID:7PwBIIdR >>490
それともHaskellという言語は何でもかんでもある数学的に説明できるように設計されていて気持ちがいいというだけのことでしょうか?
それともHaskellという言語は何でもかんでもある数学的に説明できるように設計されていて気持ちがいいというだけのことでしょうか?
493デフォルトの名無しさん
2020/09/09(水) 18:50:44.11ID:N/YnHGom 低学歴の数学弱いなのに、頑張ってHaskellで開発の会社に潜り込んで仕事してる人も居るから。
494デフォルトの名無しさん
2020/09/09(水) 19:41:50.73ID:YuHH3QPI 高卒のワイでもプロのHaskellerになれるん?
その方法教えて欲しいわ。
その方法教えて欲しいわ。
495デフォルトの名無しさん
2020/09/09(水) 19:44:40.13ID:7PwBIIdR 仕事でHaskellを使っている会社があるのですか?
実用面でのHaskellの利点があるということですか?
実用面でのHaskellの利点があるということですか?
496デフォルトの名無しさん
2020/09/09(水) 19:58:00.07ID:7PwBIIdR 「Haskellの美しさを知っている人は、人生に絶望することはない。Haskellで世界を変えたい。」などと表紙に書かれているHaskellの本が
ありますが、そんな大げさなものでしょうか?
単なる一プログラミング言語ではないんですか?
ありますが、そんな大げさなものでしょうか?
単なる一プログラミング言語ではないんですか?
497デフォルトの名無しさん
2020/09/09(水) 20:15:19.85ID:+oYkcMI9 型システムが強力ってだけで実用上有利
現実、型がしょぼい言語よりバグ減るし、
型から関数探せるから既存プログラムの再利用性高いし、
ウェイがノリで作る「イケてる」オレオレライブラリなんかにも型の合うある程度まともな設計が求められるし
現実、型がしょぼい言語よりバグ減るし、
型から関数探せるから既存プログラムの再利用性高いし、
ウェイがノリで作る「イケてる」オレオレライブラリなんかにも型の合うある程度まともな設計が求められるし
498デフォルトの名無しさん
2020/09/09(水) 20:16:27.76ID:YuHH3QPI それは持てる者がほざく絵空事やでw
499デフォルトの名無しさん
2020/09/09(水) 20:56:40.04ID:/Y+BdKRx んじゃ、async/awaitがモナドで実装できるんやでー
詳細はしらんけどw
詳細はしらんけどw
500デフォルトの名無しさん
2020/09/09(水) 22:27:03.69ID:M9aZojkl IDEは何がおすすめ?
501デフォルトの名無しさん
2020/09/10(木) 02:20:35.45ID:6Lrmk0HC らっきょ
502デフォルトの名無しさん
2020/09/10(木) 08:33:57.45ID:OHVt/ux7 俺も聞きたいけどVScodeじゃ辛い?
503デフォルトの名無しさん
2020/09/10(木) 13:10:19.99ID:he9lsIhb >>496
理解した途端にこんなしょーもないことでドやってたのかと絶望するよ。
理解した途端にこんなしょーもないことでドやってたのかと絶望するよ。
504デフォルトの名無しさん
2020/09/12(土) 10:38:44.00ID:A2+hHxph [分数モナド](https://ncatlab.org/nlab/show/Grothendieck+group+of+a+commutative+monoid)
日常生活でも目にする`2 / 3`のような分数表記はモナドになっている。
吸収元の問題があるので、ネタとしては引き算`2 - 3`の方が扱いやすいが、
引き算の場合、`2 - 3 = - 1`のように計算してしまった結果が使われ、
日常生活では生々しいモナド表記はあまり使われない。その点、分数では、
直積からのコンストラクターをもろに使った漢な表現が
日常生活の中で使われている。
分数は、モナドを使うことと、モナドを理解することは別腹という
良い例になっている気がする。分数がモナドになっていることが生きてくるのは、
システムがそれなりに複雑になってからじゃないかと思う。抽象化には
コストがかかるので、そのコストに見合った見返りが必要になるが、
システムが簡単だと、抽象化のコストをペイできない。
分数モナドは有名な例なので、何処かのブログで紹介されていると思うが、
見たことがないので、書いてみた。ホームが可換モノイドの圏なので、
オレオレモナドになってしまうが、モナド則の`QuickCheck`はできるので、
圏論の練習になるかもしれない。
日常生活でも目にする`2 / 3`のような分数表記はモナドになっている。
吸収元の問題があるので、ネタとしては引き算`2 - 3`の方が扱いやすいが、
引き算の場合、`2 - 3 = - 1`のように計算してしまった結果が使われ、
日常生活では生々しいモナド表記はあまり使われない。その点、分数では、
直積からのコンストラクターをもろに使った漢な表現が
日常生活の中で使われている。
分数は、モナドを使うことと、モナドを理解することは別腹という
良い例になっている気がする。分数がモナドになっていることが生きてくるのは、
システムがそれなりに複雑になってからじゃないかと思う。抽象化には
コストがかかるので、そのコストに見合った見返りが必要になるが、
システムが簡単だと、抽象化のコストをペイできない。
分数モナドは有名な例なので、何処かのブログで紹介されていると思うが、
見たことがないので、書いてみた。ホームが可換モノイドの圏なので、
オレオレモナドになってしまうが、モナド則の`QuickCheck`はできるので、
圏論の練習になるかもしれない。
505デフォルトの名無しさん
2020/09/12(土) 20:26:45.44ID:TbuoUVLB は?何言ってんの
506デフォルトの名無しさん
2020/09/13(日) 08:12:50.88ID:Tso/1gLY ひ?何言ってんの
507デフォルトの名無しさん
2020/09/13(日) 14:14:05.81ID:7XfXIlf2 >>504
return と >>= は何になるんですか?
return と >>= は何になるんですか?
508デフォルトの名無しさん
2020/09/13(日) 15:14:54.14ID:Gippd8g0 しらないけど
return x = x / x
ぐらいしか定義できなさそう
return x = x / x
ぐらいしか定義できなさそう
509デフォルトの名無しさん
2020/09/13(日) 21:12:53.92ID:Tso/1gLY ふ?何言ってんの
可換モノイドの圏は集合の圏の
[部分圏](https://ncatlab.org/nlab/show/subcategory)だが、
集合の圏ではない。したがって、分数モナドは、
Haskellの`Monad`のインスタンスにならない。
例えば、次のような実装を考えると、
``` code
newtype Bunsu a = Bunsu {
runBunsu :: (a, a)
} deriving (Show, Functor)
instance (Eq a, Semigroup a) => Eq (Bunsu a) where ...
instance (Semigroup a) => Semigroup (Bunsu a) where ...
instance (Monoid a) => Monoid (Bunsu a) where ...
instance (Monoid a) => Group (Bunsu a) where ...
bunsu_pure :: (Monoid a) => a -> Bunsu a
bunsu_pure = ...
```
縛り`Monoid a`が邪魔をして、`Bunsu`は`Applicative`のインスタンスに
できない。それでも、通常の関数の形でなら`bunsu_pure`と`bunsu_join`は
書けるので、モナド則のチェックはできる。ただし、`Bunsu`は、
可換モノイドの圏でのモナド則は満たすが、集合の圏でのモナド則は満たさない。
質問への直接の答えは避けるが、可換モノイドの圏で考えないと
答えは得られない。
可換モノイドの圏は集合の圏の
[部分圏](https://ncatlab.org/nlab/show/subcategory)だが、
集合の圏ではない。したがって、分数モナドは、
Haskellの`Monad`のインスタンスにならない。
例えば、次のような実装を考えると、
``` code
newtype Bunsu a = Bunsu {
runBunsu :: (a, a)
} deriving (Show, Functor)
instance (Eq a, Semigroup a) => Eq (Bunsu a) where ...
instance (Semigroup a) => Semigroup (Bunsu a) where ...
instance (Monoid a) => Monoid (Bunsu a) where ...
instance (Monoid a) => Group (Bunsu a) where ...
bunsu_pure :: (Monoid a) => a -> Bunsu a
bunsu_pure = ...
```
縛り`Monoid a`が邪魔をして、`Bunsu`は`Applicative`のインスタンスに
できない。それでも、通常の関数の形でなら`bunsu_pure`と`bunsu_join`は
書けるので、モナド則のチェックはできる。ただし、`Bunsu`は、
可換モノイドの圏でのモナド則は満たすが、集合の圏でのモナド則は満たさない。
質問への直接の答えは避けるが、可換モノイドの圏で考えないと
答えは得られない。
510デフォルトの名無しさん
2020/09/13(日) 23:57:07.12ID:Tso/1gLY へ?何言ってんの
もしかすると、何言ってんのが前の投稿にかかっちゃったかもしれない。
何も考えずに、何言ってんのおじさんプレイを楽しんでいるだけなので、
気にしないでほしい。
ついでなので。
`return x = x / x`という選択は、集合の圏では、取りうる唯一の選択肢かも
しれない。自分も他に思いつかない。しかし、可換モノイドの圏では、
他にも選択肢がある。それも含めて、
[記事](https://ncatlab.org/nlab/show/Grothendieck+group+of+a+commutative+monoid)
に全て書いてある。他人事なので断言してしまうが、この記事より詳しい
分数モナドの解説は地球上には存在しない。しかし、悲しいかな、
Haskellの解説記事と同じで、
* わかる人にはわかるが、
* わからん人にはなるほどわからん
といういつものパターンになっていると思う。解説案件の宿命かもね。
もしかすると、何言ってんのが前の投稿にかかっちゃったかもしれない。
何も考えずに、何言ってんのおじさんプレイを楽しんでいるだけなので、
気にしないでほしい。
ついでなので。
`return x = x / x`という選択は、集合の圏では、取りうる唯一の選択肢かも
しれない。自分も他に思いつかない。しかし、可換モノイドの圏では、
他にも選択肢がある。それも含めて、
[記事](https://ncatlab.org/nlab/show/Grothendieck+group+of+a+commutative+monoid)
に全て書いてある。他人事なので断言してしまうが、この記事より詳しい
分数モナドの解説は地球上には存在しない。しかし、悲しいかな、
Haskellの解説記事と同じで、
* わかる人にはわかるが、
* わからん人にはなるほどわからん
といういつものパターンになっていると思う。解説案件の宿命かもね。
511デフォルトの名無しさん
2020/09/14(月) 02:32:09.85ID:TxRaIMAU >>=は何ですか?
512デフォルトの名無しさん
2020/09/14(月) 02:44:47.64ID:SnB9iMGf 圏論わからんからなんもわからん
513デフォルトの名無しさん
2020/09/14(月) 16:41:03.56ID:TxRaIMAU Monad という概念が数学の圏論の Monad から来るのはよく解説が見つかるんですが、Applicative (≒Monoidal) については数学からの意味付けが見つかりません
コレ数学的にはなんなんですか?
コレ数学的にはなんなんですか?
514デフォルトの名無しさん
2020/09/14(月) 23:29:35.74ID:XfiH3m4/ そのままじゃん アプリカティブファンクター
なんだから、そのまま日本語訳でよくね
つまり、関手 プログラマーにとって使いやすくしただけ
ところで、”Applicative (≒Monoidal)”なのか?
こっちの方がい意味不明なんだが
モノイドって意味なら、≒モナド の方
モナイド則=モノイド則 モナドの方は、自己関手って条件が付くだけ
しらんけど
なんだから、そのまま日本語訳でよくね
つまり、関手 プログラマーにとって使いやすくしただけ
ところで、”Applicative (≒Monoidal)”なのか?
こっちの方がい意味不明なんだが
モノイドって意味なら、≒モナド の方
モナイド則=モノイド則 モナドの方は、自己関手って条件が付くだけ
しらんけど
515デフォルトの名無しさん
2020/09/15(火) 00:17:11.21ID:wUKRYY2O >>514
まだ自分でハッキリ確かめたわけじゃないんですけど
Applicative と Monoidal は同型なんだそうです
https://qiita.com/Guvalif/items/7f893d9a078e03c9e425
まだこっちはどういう意味で“同型”になるのかわかってませんけど
数学的な意味でのMonadは英語のwikiに詳しく説明が載ってて↓
https://en.m.wikipedia.org/wiki/Monad_(category_theory)
このFormal DefinitionがまさにHaskellのモナド則に繋がっていくのは確かめました
問題はApplicativeは圏論のどの概念に該当するのかの説明がサッパリ見つからないんです
まだ自分でハッキリ確かめたわけじゃないんですけど
Applicative と Monoidal は同型なんだそうです
https://qiita.com/Guvalif/items/7f893d9a078e03c9e425
まだこっちはどういう意味で“同型”になるのかわかってませんけど
数学的な意味でのMonadは英語のwikiに詳しく説明が載ってて↓
https://en.m.wikipedia.org/wiki/Monad_(category_theory)
このFormal DefinitionがまさにHaskellのモナド則に繋がっていくのは確かめました
問題はApplicativeは圏論のどの概念に該当するのかの説明がサッパリ見つからないんです
516デフォルトの名無しさん
2020/09/15(火) 02:19:25.61ID:PObv6BQ8 (a -> b) -> (m a -> m b)
m (a -> b) -> (m a -> m b)
(a -> m b) -> (m a -> m b)
こいつらは中央の->と左右の->を区別してないから数学的な意味が見えない
returnとjoinは->が一つしかないから問題ないが
m (a -> b) -> (m a -> m b)
(a -> m b) -> (m a -> m b)
こいつらは中央の->と左右の->を区別してないから数学的な意味が見えない
returnとjoinは->が一つしかないから問題ないが
517デフォルトの名無しさん
2020/09/15(火) 10:15:51.98ID:TeSbfrM9 >>516
そう、Haskellの圏論がらみの話はその“冪対象”(exponential object)が絡むのがややこしい
しかしFunctorは当然としてMonadも冪対象を用いないで形式化されてる(というより計算論の世界への応用のずっと以前からある)
Applicative(=Monoid?)はどやねんという話なんです
圏論の世界ではなかったものが計算論の世界に導入されてから考え出されたもんなんですかねぇ?
そう、Haskellの圏論がらみの話はその“冪対象”(exponential object)が絡むのがややこしい
しかしFunctorは当然としてMonadも冪対象を用いないで形式化されてる(というより計算論の世界への応用のずっと以前からある)
Applicative(=Monoid?)はどやねんという話なんです
圏論の世界ではなかったものが計算論の世界に導入されてから考え出されたもんなんですかねぇ?
518デフォルトの名無しさん
2020/09/16(水) 01:31:29.62ID:yuR5T5xB strong lax monoical functor
519デフォルトの名無しさん
2020/09/16(水) 22:12:52.40ID:CfmtxJKj モノイド圏とかモノイド対象とかあんのだけど、モノイド(モノイダル)関手ってのもあんのね
読む気は無いんだけど、アプリカティブ関手とモノイダルXXが同型ってのは無いと思うが
っておもったけど、関手同士なんだから、いくつか条件つければモナドとモノイドみたいな関係もありうるんかな?
あとは、カン拡張、随伴、普遍性(極限だっけ?) どれかから相互に変換出来るだっけ?みたいなもん?
どちらにしろ、定義の話で面白みは無いとは思うのだが
読む気は無いんだけど、アプリカティブ関手とモノイダルXXが同型ってのは無いと思うが
っておもったけど、関手同士なんだから、いくつか条件つければモナドとモノイドみたいな関係もありうるんかな?
あとは、カン拡張、随伴、普遍性(極限だっけ?) どれかから相互に変換出来るだっけ?みたいなもん?
どちらにしろ、定義の話で面白みは無いとは思うのだが
520デフォルトの名無しさん
2020/09/17(木) 10:32:26.07ID:2a8IoKJu 見つけた
https://qiita.com/Guvalif/items/7f893d9a078e03c9e425
このサイトの人がまとめたpdfに書いてある
とは言ってもやはりclosed categoryは仮定してる
やっぱりapplicativeはmonadと違って“内部ホム”を持たない圏では定義できないんだろな
“内部ホム”もつ圏でmonoidal functorに<*>を定義するのはわりと簡単だけど↓
F(X) × F(Y^X)
→F(X×Y^X) (coherence)
→F(Y) (F(eval))
https://en.m.wikipedia.org/wiki/Monoidal_functor
pureが全然できんなぁと思ってたら“strong”という条件からpureが作れるんだな
まぁHaskellて圏の話するときはHASKて言えればいいんだからコレでわかったことにしよ
https://qiita.com/Guvalif/items/7f893d9a078e03c9e425
このサイトの人がまとめたpdfに書いてある
とは言ってもやはりclosed categoryは仮定してる
やっぱりapplicativeはmonadと違って“内部ホム”を持たない圏では定義できないんだろな
“内部ホム”もつ圏でmonoidal functorに<*>を定義するのはわりと簡単だけど↓
F(X) × F(Y^X)
→F(X×Y^X) (coherence)
→F(Y) (F(eval))
https://en.m.wikipedia.org/wiki/Monoidal_functor
pureが全然できんなぁと思ってたら“strong”という条件からpureが作れるんだな
まぁHaskellて圏の話するときはHASKて言えればいいんだからコレでわかったことにしよ
521デフォルトの名無しさん
2020/09/28(月) 01:41:48.03ID:0EuZ+v5t [Promise](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise)
の小さい例題の[html](https://pastebin.com/yxSRyg2u)をアップした。
async/awaitはPromiseのお助け文法になっているが、それは扱っていない。実行環境は、
[RStudio](https://rstudio.com/products/rstudio/)から
[Node.js](https://nodejs.org/ja/)を呼び出している。
の小さい例題の[html](https://pastebin.com/yxSRyg2u)をアップした。
async/awaitはPromiseのお助け文法になっているが、それは扱っていない。実行環境は、
[RStudio](https://rstudio.com/products/rstudio/)から
[Node.js](https://nodejs.org/ja/)を呼び出している。
522デフォルトの名無しさん
2020/10/14(水) 04:31:41.26ID:+VLXbnA3 >>20
ワードカウントのロジックが不思議ちゃんだと思ったけどワードと空白の関係が
"abc dd "みたいな行儀が良い書式じゃないとだめなんだな
" "一文字スペースでワード数が1になってしまうみたいな
countFile :: String -> (Int, Int, Int)
countFile s =
let (cs, ws, ls, _) = foldl' go (0, 0, 0, False) s
in (cs, ws, ls)
where
go :: (Int, Int, Int, Bool) -> Char -> (Int, Int, Int, Bool)
go (cs, ws, ls, wasSpace) c =
let addLine | c == '\n' = 1
| otherwise = 0
addWord | wasSpace = 0
| isSpace c = 1
| otherwise = 0
in (cs + 1, ws + addWord, ls + addLine, isSpace c)
ワードカウントのロジックが不思議ちゃんだと思ったけどワードと空白の関係が
"abc dd "みたいな行儀が良い書式じゃないとだめなんだな
" "一文字スペースでワード数が1になってしまうみたいな
countFile :: String -> (Int, Int, Int)
countFile s =
let (cs, ws, ls, _) = foldl' go (0, 0, 0, False) s
in (cs, ws, ls)
where
go :: (Int, Int, Int, Bool) -> Char -> (Int, Int, Int, Bool)
go (cs, ws, ls, wasSpace) c =
let addLine | c == '\n' = 1
| otherwise = 0
addWord | wasSpace = 0
| isSpace c = 1
| otherwise = 0
in (cs + 1, ws + addWord, ls + addLine, isSpace c)
523デフォルトの名無しさん
2020/10/31(土) 09:11:59.11ID:UJYxitvT http://walk.northcol.org/haskell/adts/
>代数的データ型(algebraic data type)とは,図のように木構造で表現される値からなるデータ型のことです.
必ず木構造に限定されるんだろうか?
OOPではオブジェクトグラフがありネットワークになりうるが、
Haskellでは絶対に木と考えて良いの?
>代数的データ型(algebraic data type)とは,図のように木構造で表現される値からなるデータ型のことです.
必ず木構造に限定されるんだろうか?
OOPではオブジェクトグラフがありネットワークになりうるが、
Haskellでは絶対に木と考えて良いの?
524デフォルトの名無しさん
2020/10/31(土) 12:29:50.75ID:cEs7BAmA いいんじゃない?
型の全体は文脈自由文法で規定されるクラスだから木になる希ガス
型の全体は文脈自由文法で規定されるクラスだから木になる希ガス
525デフォルトの名無しさん
2020/10/31(土) 12:34:33.57ID:fxcwqRC2 この木なんの木きのこる木
526デフォルトの名無しさん
2020/10/31(土) 12:37:07.03ID:CAmth+XY 見たこともない木ですから
独自実装のバグが出るでしょう
独自実装のバグが出るでしょう
527デフォルトの名無しさん
2020/10/31(土) 13:17:41.17ID:cEs7BAmA でもよくよく考えたらHaskellのデータ型って「展開できる表現がひとつもないデータ型」もありうるんだな
無限の木になる
data InfiniteSequence = IS {car :: Int, cdr :: InfiniteSequence}
arithSeq a d = IS a $ arithSeq (a+d) d
term 0 (IS x y) = x
term n (IS x y) = term (n-1) y
main = print $ term 10 $ arithSeq 5 3
----
53
無限の木になる
data InfiniteSequence = IS {car :: Int, cdr :: InfiniteSequence}
arithSeq a d = IS a $ arithSeq (a+d) d
term 0 (IS x y) = x
term n (IS x y) = term (n-1) y
main = print $ term 10 $ arithSeq 5 3
----
53
528デフォルトの名無しさん
2020/10/31(土) 13:26:01.44ID:UJYxitvT 再帰的なデータ型はグラフにできるのでは?
529デフォルトの名無しさん
2020/10/31(土) 13:37:30.03ID:B0ELcd4k 最終的に暴走しないで展開が停止するものだけをデータ型と呼ぶならそうだけど、iterate (+4) 5 ですら無限の木になってしまう
530デフォルトの名無しさん
2020/10/31(土) 21:13:27.13ID:3k5Im+3l haskellの配列は代数的データ型でばないのか?
531デフォルトの名無しさん
2020/10/31(土) 22:07:18.29ID:XiPKdEPZ foldrなどの引数のことを代数的と言っていたような気がする
引数は(:)と[]でもいいし
(+)と0でもいい
引数を渡すと関数 [a] -> b が返ってくるが
これは関数というよりOOPの継承関係のような印象
引数は(:)と[]でもいいし
(+)と0でもいい
引数を渡すと関数 [a] -> b が返ってくるが
これは関数というよりOOPの継承関係のような印象
532デフォルトの名無しさん
2020/10/31(土) 22:34:53.43ID:B0ELcd4k Haskell のデータ型は再帰を許すからな
どうしても「終端記号(大文字から始まるData constructet) を木構造に並べたもの」という説明をしたいなら無限グラフを使わざるをえない
どうしても「終端記号(大文字から始まるData constructet) を木構造に並べたもの」という説明をしたいなら無限グラフを使わざるをえない
533デフォルトの名無しさん
2020/11/01(日) 07:14:51.56ID:fIYIMdhR http://walk.northcol.org/haskell/lists/#_%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AE%E7%95%B3%E8%BE%BC%E3%81%BF
1)foldr (+) 0 [1, 2, 3]
(+)とカッコがつく理由は?
2)map' f = foldr (\x a -> f x : a) []
xは[]の各要素?aは何?
1)foldr (+) 0 [1, 2, 3]
(+)とカッコがつく理由は?
2)map' f = foldr (\x a -> f x : a) []
xは[]の各要素?aは何?
534デフォルトの名無しさん
2020/11/01(日) 08:58:44.92ID:Srz4hpJo 1)
http://walk.northcol.org/haskell/operators/#_%E4%B8%AD%E7%BD%AE%E3%81%A8%E5%89%8D%E7%BD%AE%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88
2)
このままだと対応する値が存在しないので、少し書き換える
map' f xs = foldr (\x a -> f x : a) [] xs
xはxsの各要素、aは最後の要素では[]で、
それ以前は後ろの要素に(\x a -> f x : a)を適用した結果
http://walk.northcol.org/haskell/operators/#_%E4%B8%AD%E7%BD%AE%E3%81%A8%E5%89%8D%E7%BD%AE%E3%81%AE%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88
2)
このままだと対応する値が存在しないので、少し書き換える
map' f xs = foldr (\x a -> f x : a) [] xs
xはxsの各要素、aは最後の要素では[]で、
それ以前は後ろの要素に(\x a -> f x : a)を適用した結果
535デフォルトの名無しさん
2020/11/01(日) 09:15:58.91ID:v6ASK7zT >>533
>
> 1)foldr (+) 0 [1, 2, 3]
> (+)とカッコがつく理由は?
+ がないと+は中置演算子で
(foldr + 0) [1, 2, 3]
になる
(+)があると普通の関数としてfoldrの因数として解釈される
> 2)map' f = foldr (\x a -> f x : a) []
> xは[]の各要素?aは何?
[]はfoldrの第3因数と同じ型の空集合
a は無名函数(\x a -> f x : a)の第2因数
定義に従ってmap' sin [] [5,6]] はわかりやすく(\x a -> sin x : a)を中置演算子++++で書くと(すなわちx ++++ a = (sin x) : aとすると)
map' sin [] [5,6]
= 5 ++++ ( 6 ++++ [] )
= 5 ++++ ( (sin 6) : [] )
= 5 ++++ [ (sin 6) ]
= [ (sin 5) : [ (sin 6) ]
= [ (sin 5) , (sin 6) ]
となる
>
> 1)foldr (+) 0 [1, 2, 3]
> (+)とカッコがつく理由は?
+ がないと+は中置演算子で
(foldr + 0) [1, 2, 3]
になる
(+)があると普通の関数としてfoldrの因数として解釈される
> 2)map' f = foldr (\x a -> f x : a) []
> xは[]の各要素?aは何?
[]はfoldrの第3因数と同じ型の空集合
a は無名函数(\x a -> f x : a)の第2因数
定義に従ってmap' sin [] [5,6]] はわかりやすく(\x a -> sin x : a)を中置演算子++++で書くと(すなわちx ++++ a = (sin x) : aとすると)
map' sin [] [5,6]
= 5 ++++ ( 6 ++++ [] )
= 5 ++++ ( (sin 6) : [] )
= 5 ++++ [ (sin 6) ]
= [ (sin 5) : [ (sin 6) ]
= [ (sin 5) , (sin 6) ]
となる
536デフォルトの名無しさん
2020/11/01(日) 10:14:49.54ID:1eMkmBeN 因数?引数ではなく?
Haskell用語なのかな
Haskell用語なのかな
537デフォルトの名無しさん
2020/11/01(日) 10:21:30.53ID:Srz4hpJo 1)
foldr + 0 [1,2,3]
と書いた場合、「+」より関数適用のほうが優先順位が高いので、
foldr + (0 [1,2,3])
と解釈される。
つまり、0という関数を[1,2,3]という引数に適用したものと、foldrを足し算するという意味となる
2)
具体例
map' f [1,2,3] = foldr (\x a -> f x : a) [1,2,3]
3番目の値
(\x a -> f x : a) 3 [] = f 3 : [] = [f 3]
2番目の値
(\x a -> f x : a) 2 [f 3] = f 2 : [f 3] = [f 2, f 3]
1番目の値
(\x a -> f x : a) 1 [f 2, f 3] = f 1 : [f 2, f 3] = [f 1, f 2, f 3]
foldr + 0 [1,2,3]
と書いた場合、「+」より関数適用のほうが優先順位が高いので、
foldr + (0 [1,2,3])
と解釈される。
つまり、0という関数を[1,2,3]という引数に適用したものと、foldrを足し算するという意味となる
2)
具体例
map' f [1,2,3] = foldr (\x a -> f x : a) [1,2,3]
3番目の値
(\x a -> f x : a) 3 [] = f 3 : [] = [f 3]
2番目の値
(\x a -> f x : a) 2 [f 3] = f 2 : [f 3] = [f 2, f 3]
1番目の値
(\x a -> f x : a) 1 [f 2, f 3] = f 1 : [f 2, f 3] = [f 1, f 2, f 3]
538デフォルトの名無しさん
2020/11/01(日) 10:25:40.23ID:Srz4hpJo おっと、具体例の「foldr (\x a -> f x : a) [1,2,3]」は
「foldr (\x a -> f x : a) [] [1,2,3]」の誤り
「foldr (\x a -> f x : a) [] [1,2,3]」の誤り
539デフォルトの名無しさん
2020/11/01(日) 10:36:13.55ID:B/d//mYI い・・・引数
540デフォルトの名無しさん
2020/11/01(日) 10:54:46.55ID:z/eHKN3/ 引数です
orz
普段“因数”の方が使う人なのでうっかりしたorz
orz
普段“因数”の方が使う人なのでうっかりしたorz
541デフォルトの名無しさん
2020/11/01(日) 11:03:53.67ID:93fSMn/e こ・・・因数
542デフォルトの名無しさん
2020/11/01(日) 11:05:28.12ID:z/eHKN3/ こ?
543デフォルトの名無しさん
2020/11/01(日) 11:11:25.51ID:4+fLUvoM だ…因数
544デフォルトの名無しさん
2020/11/01(日) 12:57:34.37ID:9/8GaKcH ひきすう
545デフォルトの名無しさん
2020/11/01(日) 15:22:11.82ID:N8AW169o 引数を「ひきすう」と読むのは、同音異義語との混同を避けるための慣用読みだと思ってた
化学(ばけがく)、鼻腔(びくう)みたいな
化学(ばけがく)、鼻腔(びくう)みたいな
546デフォルトの名無しさん
2020/11/01(日) 15:24:45.41ID:BdB3gM+x 返り血
547デフォルトの名無しさん
2020/11/01(日) 17:34:03.38ID:S9fsJ+JS Parameterとargumentsの違いがよくわからない
548デフォルトの名無しさん
2020/11/01(日) 17:44:50.76ID:5aO2zs3I549デフォルトの名無しさん
2020/11/01(日) 17:59:46.68ID:S9fsJ+JS よくわからんし一緒ってことか
550デフォルトの名無しさん
2020/11/02(月) 00:43:34.64ID:TnMF05Pn 質問です
このサイトでNum instanceをDerivingする話が出てました
https://qiita.com/HirotoShioi/items/8a6107434337b30ce457
実際このページの次のコードはうちの環境でも通ります
Haskell Online Compiler [ghc-8.4.4]
Copyright (c) The University of Glasgow
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Quantity = Quantity Int
deriving (Eq, Ord, Num, Show)
a = Quantity 2
b = Quantity 6
totalQuantity :: Quantity
totalQuantity = a + b
-- Quantity 8
しかし次は通りません
通す事はできますか?
import Text.ParserCombinators.Parsec
import Text.Parsec (Parsec)
newtype ParserInt = PI (Parser Int) deriving (Num)
このサイトでNum instanceをDerivingする話が出てました
https://qiita.com/HirotoShioi/items/8a6107434337b30ce457
実際このページの次のコードはうちの環境でも通ります
Haskell Online Compiler [ghc-8.4.4]
Copyright (c) The University of Glasgow
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Quantity = Quantity Int
deriving (Eq, Ord, Num, Show)
a = Quantity 2
b = Quantity 6
totalQuantity :: Quantity
totalQuantity = a + b
-- Quantity 8
しかし次は通りません
通す事はできますか?
import Text.ParserCombinators.Parsec
import Text.Parsec (Parsec)
newtype ParserInt = PI (Parser Int) deriving (Num)
551デフォルトの名無しさん
2020/11/02(月) 00:43:43.72ID:TnMF05Pn ---- エラーメッセージ
Haskell Online Compiler [ghc-8.4.4]
Copyright (c) The University of Glasgow
Compiling your program...
[1 of 1] Compiling Main ( prog.hs, prog.o )
prog.hs:6:47: error:
• No instance for (Num (Parser Int))
arising from the 'deriving' clause of a data type declaration
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Num ParserInt)
|
6 | newtype ParserInt = PI (Parser Int) deriving (Num)
| ^^^
Haskell Online Compiler [ghc-8.4.4]
Copyright (c) The University of Glasgow
Compiling your program...
[1 of 1] Compiling Main ( prog.hs, prog.o )
prog.hs:6:47: error:
• No instance for (Num (Parser Int))
arising from the 'deriving' clause of a data type declaration
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Num ParserInt)
|
6 | newtype ParserInt = PI (Parser Int) deriving (Num)
| ^^^
552デフォルトの名無しさん
2020/11/02(月) 21:44:04.17ID:aBc5dqas こうすりゃ無理やり通すことはできるけど、
そもそもパーサ同士の足し算等々でどう動いて欲しいのか分からんから
まともなインスタンス宣言が書けん
{-# LANGUAGE FlexibleInstances #-}
instance Num (Parser Int) where
x + y = x
x * y = x
abs x = x
signum x = x
negate x = x
fromInteger n = return 0
そもそもパーサ同士の足し算等々でどう動いて欲しいのか分からんから
まともなインスタンス宣言が書けん
{-# LANGUAGE FlexibleInstances #-}
instance Num (Parser Int) where
x + y = x
x * y = x
abs x = x
signum x = x
negate x = x
fromInteger n = return 0
553デフォルトの名無しさん
2020/11/02(月) 23:56:16.57ID:Zq9JUsOb >>552
元は別スレに出てた問題で
「与えられた文字列の中で“trickと"treat”どっちが先に出てくるか判定せよ」
なんです
とりあえずparserを与える関数として
makeP = mconcat . map ( manyTill anyChar . char )
でできました
コレを例えば"abc"にapplyするとmtl = manyTill、ac=anyCharとして
(mtl ac $ char 'a') <> (mtl ac $ char 'b') <> (mtl ac $ char 'c'>
というparserになりコレにhiajklbcnという文字列をparseするとhijklとabcが出現するするまでに読み飛ばした文字列を返してくれます
それでお題の答えとしてparseの結果を
lastInd x s = case ( runParser ( makeP x ) () "" s ) of
Left _ -> ( [ 2, 0 ] , x )
Right y -> ( [ 0, length $ x ++ y ], x )
のようにしてlengthで数えたんです
しかしちょっと冗長なかんじがします
そもそも読み飛ばした文字列なんか欲しいわけではなく読み飛ばした文字数が欲しいだけだからほんとは
Parser String 型ではなく例えば
length <$> ( manyTill anyChar ( char 'x')
とかのParser Intで十分です
問題はコレをどうやって繋げて総和を返すコンビネータを作ろうかというところなんです
Parser Stringはmonoid型を持ってるのでmconcat一発で繋げられるんですがParser IntはNum持ってないのでsum一発で繋げるというわけにはいかないんです
なんとかできないかと探してみるとなんか「Numをderivingする」という記事を見つけて、お、コレでいけないかと色々やってみたんですがやはりParser Intにderiving一髪でNum入れる方法見つからなくてなんとかならんもんかと
元は別スレに出てた問題で
「与えられた文字列の中で“trickと"treat”どっちが先に出てくるか判定せよ」
なんです
とりあえずparserを与える関数として
makeP = mconcat . map ( manyTill anyChar . char )
でできました
コレを例えば"abc"にapplyするとmtl = manyTill、ac=anyCharとして
(mtl ac $ char 'a') <> (mtl ac $ char 'b') <> (mtl ac $ char 'c'>
というparserになりコレにhiajklbcnという文字列をparseするとhijklとabcが出現するするまでに読み飛ばした文字列を返してくれます
それでお題の答えとしてparseの結果を
lastInd x s = case ( runParser ( makeP x ) () "" s ) of
Left _ -> ( [ 2, 0 ] , x )
Right y -> ( [ 0, length $ x ++ y ], x )
のようにしてlengthで数えたんです
しかしちょっと冗長なかんじがします
そもそも読み飛ばした文字列なんか欲しいわけではなく読み飛ばした文字数が欲しいだけだからほんとは
Parser String 型ではなく例えば
length <$> ( manyTill anyChar ( char 'x')
とかのParser Intで十分です
問題はコレをどうやって繋げて総和を返すコンビネータを作ろうかというところなんです
Parser Stringはmonoid型を持ってるのでmconcat一発で繋げられるんですがParser IntはNum持ってないのでsum一発で繋げるというわけにはいかないんです
なんとかできないかと探してみるとなんか「Numをderivingする」という記事を見つけて、お、コレでいけないかと色々やってみたんですがやはりParser Intにderiving一髪でNum入れる方法見つからなくてなんとかならんもんかと
554デフォルトの名無しさん
2020/11/03(火) 01:59:40.73ID:WdkpFDBO わざわざNumのインスタンスにしなくても、これでいいのでは
makeP = fmap sum . mapM ( fmap length . manyTill anyChar . char )
makeP = fmap sum . mapM ( fmap length . manyTill anyChar . char )
555デフォルトの名無しさん
2020/11/03(火) 10:26:04.44ID:qaG2IpUi >>554
うん、まぁ別にNumのインスタンス入れなくてもこの問題の話だけならいくらでも方法はあると思うんだけど、そもそもモナドってもこういう時のためにあるんじゃないのかなと思って
例えば(+)なら Num a,Functor f のとき Num (f a)は自然には導出できない、なぜなら fmap (+) は f a -> f ( a - > a ) になってしまう
しかし Applicative f なら lifaA2 (+) がピッタリ f a -> f a -> f a になって自然にキレイに Num (f a) が導出できる
だからすごく理論的には自然なのに方法がないのは何故なんだろうと
というかderiving (...) の (...) にかけるやつとダメなやつの基準がわからない
実用本位でよく使うやつだけ用意されてるに過ぎないのかな?
うん、まぁ別にNumのインスタンス入れなくてもこの問題の話だけならいくらでも方法はあると思うんだけど、そもそもモナドってもこういう時のためにあるんじゃないのかなと思って
例えば(+)なら Num a,Functor f のとき Num (f a)は自然には導出できない、なぜなら fmap (+) は f a -> f ( a - > a ) になってしまう
しかし Applicative f なら lifaA2 (+) がピッタリ f a -> f a -> f a になって自然にキレイに Num (f a) が導出できる
だからすごく理論的には自然なのに方法がないのは何故なんだろうと
というかderiving (...) の (...) にかけるやつとダメなやつの基準がわからない
実用本位でよく使うやつだけ用意されてるに過ぎないのかな?
556デフォルトの名無しさん
2020/11/03(火) 11:32:34.46ID:WdkpFDBO 一応、Num (f a)は導出できるけど、それで定義した(+)だと
交換則(x + y = y + x)が成り立つ保証がないからじゃないかねぇ
(パーサの順番を入れ替えた場合を考えるとわかりやすい)
{-# LANGUAGE FlexibleInstances #-}
instance (Num a, Applicative f) => Num (f a) where
x + y = (+) <$> x <*> y
x * y = (*) <$> x <*> y
abs x = abs <$> x
signum x = signum <$> x
negate x = negate <$> x
fromInteger n = pure $ fromInteger n
交換則(x + y = y + x)が成り立つ保証がないからじゃないかねぇ
(パーサの順番を入れ替えた場合を考えるとわかりやすい)
{-# LANGUAGE FlexibleInstances #-}
instance (Num a, Applicative f) => Num (f a) where
x + y = (+) <$> x <*> y
x * y = (*) <$> x <*> y
abs x = abs <$> x
signum x = signum <$> x
negate x = negate <$> x
fromInteger n = pure $ fromInteger n
557デフォルトの名無しさん
2020/11/03(火) 11:50:57.17ID:hn8kPJNe >>556
なるほど、文法的に通っても意味的に文法には出てこない"Num rule"が補償されないからダメって事なのかな?
まぁ今はclassのメンバ関数の自分が利用するやつだけ定義する必要無くなったみたいだから手で書いてもいいんだけど、>>550の例だと
newtype Eval a = Eval (ReaderT Env (ExceptT String Identity) a)
deriving (Functor, Applicative, Monad, MonadReader Env, MonadError String)
とかはmonad translater越しにできるし
newtype Quantity = Quantity Int
deriving (Eq, Ord, Num, Show)
もできるのになんで Parser (Int) はあかんねんと
なんかプラクマつけたらいけんもんかと
Num くらいならいいけど Floating とかだと惨劇になってしまう
なるほど、文法的に通っても意味的に文法には出てこない"Num rule"が補償されないからダメって事なのかな?
まぁ今はclassのメンバ関数の自分が利用するやつだけ定義する必要無くなったみたいだから手で書いてもいいんだけど、>>550の例だと
newtype Eval a = Eval (ReaderT Env (ExceptT String Identity) a)
deriving (Functor, Applicative, Monad, MonadReader Env, MonadError String)
とかはmonad translater越しにできるし
newtype Quantity = Quantity Int
deriving (Eq, Ord, Num, Show)
もできるのになんで Parser (Int) はあかんねんと
なんかプラクマつけたらいけんもんかと
Num くらいならいいけど Floating とかだと惨劇になってしまう
558デフォルトの名無しさん
2020/11/03(火) 18:12:46.66ID:oSP8TPsC この話の面白いところは
Parser Intという型を宣言する言語と
そもそも型を宣言しない言語
どっちが生産性高いかってことだよ
Parser Intという型を宣言する言語と
そもそも型を宣言しない言語
どっちが生産性高いかってことだよ
559!id:ignore
2020/11/06(金) 20:16:57.19ID:uZSEyxFl stackくんさぁ、コンパイラのダウンロードが200MB強あるんだから、低速回線は途中で切断されるとかよくありそうなことじゃん
サスペンド・レジューム機能搭載は必須じゃないのかね
きょうびyoutube-dlでさえ向こうに切断Forbiddenされても今までダウンロードした分は残ってて、再度ダウンロードを開始した際には途中から残りの部分をダウンロードすように始まるってのにさ
仮に205.86 MiB / 205.87 MiBまで来て切断された場合
リトライすると0 MiB / 205.87 MiB からだなんてお互い不幸になると思わないのか?
こっちは成功するまで永遠に繰り返すんだぞ? むしろそっちの方がそちらにとっても迷惑じゃん
それとも低速回線は死ねっていう差別的思想を持っているのかね?
サスペンド・レジューム機能搭載は必須じゃないのかね
きょうびyoutube-dlでさえ向こうに切断Forbiddenされても今までダウンロードした分は残ってて、再度ダウンロードを開始した際には途中から残りの部分をダウンロードすように始まるってのにさ
仮に205.86 MiB / 205.87 MiBまで来て切断された場合
リトライすると0 MiB / 205.87 MiB からだなんてお互い不幸になると思わないのか?
こっちは成功するまで永遠に繰り返すんだぞ? むしろそっちの方がそちらにとっても迷惑じゃん
それとも低速回線は死ねっていう差別的思想を持っているのかね?
560デフォルトの名無しさん
2020/11/08(日) 11:31:57.94ID:Bx8aZf2L 一方TeXはisoイメージを使った
561デフォルトの名無しさん
2020/11/08(日) 13:05:47.79 パターンガードの変数の束縛は局所的なのですが、全ての場合で共通して使用してほしい束縛はどうやりますか?
562デフォルトの名無しさん
2020/11/09(月) 01:15:49.21ID:4MQyK7K1563デフォルトの名無しさん
2020/11/09(月) 19:55:38.03 rootsInternal :: Quadratic -> Double -> Roots
rootsInternal q d
= let
two_a = 2.0 * (a q)
realpart = - (b q) / two_a
dside d = (sqrt d) / two_a
dpart = dside d
complexpart = dside (-d)
in if d==0
then -- Discriminant is zero, (single) root is real
Root $ realpart :+ 0
else
if d<0
then -- Discriminant is negative, roots are complex
Roots (realpart :+ complexpart) (realpart :+ (-complexpart))
else -- Discriminant is positive, all roots are real
Roots ((realpart + dpart) :+ 0) ((realpart - dpart) :+ 0)
のlet 〜 in みたいなのを
rootsInternal q d
| d==0 = ...
| d<0 = ...
| otherwise = ...
みたいな書き方の時にもやりたいんです
rootsInternal q d
= let
two_a = 2.0 * (a q)
realpart = - (b q) / two_a
dside d = (sqrt d) / two_a
dpart = dside d
complexpart = dside (-d)
in if d==0
then -- Discriminant is zero, (single) root is real
Root $ realpart :+ 0
else
if d<0
then -- Discriminant is negative, roots are complex
Roots (realpart :+ complexpart) (realpart :+ (-complexpart))
else -- Discriminant is positive, all roots are real
Roots ((realpart + dpart) :+ 0) ((realpart - dpart) :+ 0)
のlet 〜 in みたいなのを
rootsInternal q d
| d==0 = ...
| d<0 = ...
| otherwise = ...
みたいな書き方の時にもやりたいんです
564デフォルトの名無しさん
2020/11/09(月) 19:58:42.43 おっと無用な改行が一々入っちゃった。。。
565デフォルトの名無しさん
2020/11/09(月) 20:20:48.18ID:UhW/CkjO >>563-564
where で出来なかったっけ?だめだったかな?
where で出来なかったっけ?だめだったかな?
566デフォルトの名無しさん
2020/11/09(月) 21:00:20.89 あ、できました。
お騒がせしました(////)
お騒がせしました(////)
567デフォルトの名無しさん
2020/11/11(水) 19:20:13.76ID:qheOKxfd 正格評価について質問です
ひとつの引数しかない関数 f を正格評価するときには
f $! x
でよいようですが2引数の場合はどうするんですか?
( f $! x ) $! y
で x, y を先に展開してくれますか?
良さげなんですがどう確かめたものやら
なんか正格評価と遅延評価で格段に計算量が変わる f の例ってありますか?
ひとつの引数しかない関数 f を正格評価するときには
f $! x
でよいようですが2引数の場合はどうするんですか?
( f $! x ) $! y
で x, y を先に展開してくれますか?
良さげなんですがどう確かめたものやら
なんか正格評価と遅延評価で格段に計算量が変わる f の例ってありますか?
568デフォルトの名無しさん
2020/11/11(水) 21:38:04.29ID:TR1bVb0l 遅延評価がなくてもGCはメモリ解放を遅らせている
GCをいじるにはIOが必要
$!を使うのにも少なくともモナドが必要と考えるのが自然なのでは?
x' <- return $! x
y' <- return $! y
return $! (f x' y')
GCをいじるにはIOが必要
$!を使うのにも少なくともモナドが必要と考えるのが自然なのでは?
x' <- return $! x
y' <- return $! y
return $! (f x' y')
569デフォルトの名無しさん
2020/11/11(水) 22:07:05.86ID:F87BSTFR >>568
そうなんですか?
とりあえずモナドで試してみます
兎にも角にも正格評価と遅延評価でこんなに計算の回数が違ってくるってのなんかご存知ないですか?
例えばdpの例でFibonacciを
f 0 = 0
f 1 = 1
f n = (f $ n-1) + (f $ n-2)
と
f' 0 = (0,1)
f' n = (a+b,a) where (a,b) = f' (n-1)
f = fst . f'
で比べると目に見えて計算量が違うみたいな奴で「正格評価が効いてる」って目に見えてわかるような例があるとありがたいんですが
そうなんですか?
とりあえずモナドで試してみます
兎にも角にも正格評価と遅延評価でこんなに計算の回数が違ってくるってのなんかご存知ないですか?
例えばdpの例でFibonacciを
f 0 = 0
f 1 = 1
f n = (f $ n-1) + (f $ n-2)
と
f' 0 = (0,1)
f' n = (a+b,a) where (a,b) = f' (n-1)
f = fst . f'
で比べると目に見えて計算量が違うみたいな奴で「正格評価が効いてる」って目に見えてわかるような例があるとありがたいんですが
570デフォルトの名無しさん
2020/11/12(木) 14:57:12.09ID:+Y5HOlnE 正格評価と遅延評価で計算量が変わるといえばtaraiじゃね?
571デフォルトの名無しさん
2020/11/12(木) 23:16:18.57ID:G64JuFLE ⊥になるものでいいじゃん
572デフォルトの名無しさん
2020/11/13(金) 06:27:56.29ID:ewlhvLCU trace や unsafePerformIO で評価順を調べられないかな
573デフォルトの名無しさん
2020/11/13(金) 12:04:46.50ID:oAmrFI5R みなさん情報ありがとうございます
今んとこヒマな時にやってみた実現は
cube x = x*x*x
a x = case x of
0 -> 0
1 -> 1
_ -> ( a $ x -1 ) + ( a $ x - 2 )
main = do
tA <- getCPUTime
print $ cube $ a 38
tB <- getCPUTime
print $ tB - tA
と
print $ cube $ a 38 → print $ a 38
の比較
結果
----
59722225363795389930809
3801127096000
----
39088169
3514055718000
この程度だとコンパイラが勝手にメモ化してくれるようで差がでないorz
まだタライとかは試して見てません
取り急ぎご報告まで
今んとこヒマな時にやってみた実現は
cube x = x*x*x
a x = case x of
0 -> 0
1 -> 1
_ -> ( a $ x -1 ) + ( a $ x - 2 )
main = do
tA <- getCPUTime
print $ cube $ a 38
tB <- getCPUTime
print $ tB - tA
と
print $ cube $ a 38 → print $ a 38
の比較
結果
----
59722225363795389930809
3801127096000
----
39088169
3514055718000
この程度だとコンパイラが勝手にメモ化してくれるようで差がでないorz
まだタライとかは試して見てません
取り急ぎご報告まで
574デフォルトの名無しさん
2020/11/16(月) 23:33:39.07ID:bCg5e61i >>567
もうとっくに解決したかもしれませんが、評価の順は trace 関数でも確認できます。
import Debug.Trace
g :: Int -> Int -> Int
g x y = trace ("g") (x + y)
main :: IO ()
main = do
let a = trace ("a") 1
let b = trace ("b") 2
let c = (g $! a) $! b
putStrLn $ show c
これを実行すれば、b a g 3 の順に出力されます。
正格評価されていると言えます。
ちなみに、($!) を ($) に変えれば、g a b 3 の順に出力されます。
もうとっくに解決したかもしれませんが、評価の順は trace 関数でも確認できます。
import Debug.Trace
g :: Int -> Int -> Int
g x y = trace ("g") (x + y)
main :: IO ()
main = do
let a = trace ("a") 1
let b = trace ("b") 2
let c = (g $! a) $! b
putStrLn $ show c
これを実行すれば、b a g 3 の順に出力されます。
正格評価されていると言えます。
ちなみに、($!) を ($) に変えれば、g a b 3 の順に出力されます。
575デフォルトの名無しさん
2020/11/18(水) 01:05:30.21ID:VzwFaHaO576デフォルトの名無しさん
2020/11/21(土) 23:31:14.57ID:ak7brOTq Haskellはライブラリの中身を覗くと
Template Haskellを駆使した
グッチャグチャの実質別言語みたいなコードがザラなのがなぁ・・・
水面下の白鳥状態じゃねーか
Template Haskellを駆使した
グッチャグチャの実質別言語みたいなコードがザラなのがなぁ・・・
水面下の白鳥状態じゃねーか
577デフォルトの名無しさん
2020/11/22(日) 16:59:26.57ID:gt3QNmmg ゴミライブラリ使うのやめて良いやつ作って公開してくれ
578デフォルトの名無しさん
2020/11/22(日) 17:19:45.03ID:MRtbpg3I 在学中か学校出たての経験浅い奴しか担い手がいないのだろうからそんなもんなんだろう
純粋関数型言語は学生がかかるはしかみたいなもので
やがて計算機科学の現状に絶望し去ってゆく
現在のコンピューターは手続き型に最適化されているのだ
純粋関数型言語は学生がかかるはしかみたいなもので
やがて計算機科学の現状に絶望し去ってゆく
現在のコンピューターは手続き型に最適化されているのだ
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 中国側が首相答弁の撤回要求、日本側拒否 [夜のけいちゃん★]
- 中国の局長は「両手をポケット」で対峙 宣伝戦で国民に示す ★3 [蚤の市★]
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 ★4 [ぐれ★]
- 債券・円・株「トリプル安」に…長期金利1.755%まで上昇、円は対ユーロで史上最安値 [蚤の市★]
- 映画「鬼滅の刃」の興行収入急減、日本行き航空券大量キャンセル…中国メディア報道 [蚤の市★]
- 日本行き空路49万件キャンセル 中国自粛呼びかけ 日本行きチケット予約の約32%に相当 ★5 [ぐれ★]
- とらせん IPあり
- 巨専】
- 【DAZN】ワールドカップ欧州予選総合 ★5
- こいせん 全レス転載禁止
- 【J SPORTS】FIFA U-17ワールドカップ ★10
- 【ATP】テニス総合実況スレ2025 Part 211【WTA】
- トヨタ、反日だった。2027年に中国にレクサスのEV工場を設立。高市 [931948549]
- 日本政府、ネトウヨに媚びるために韓国との関係も悪化させてしまう [603416639]
- 【悲報】高市効果で「1ドル=160円」が相場へwwwwwwwwwwwwwwwwwwwwwwwwwwwww 止まらぬ高市円安💥💥 [871926377]
- 【悲報】SP500今日も暴落で完全に世界恐慌。高市恐慌として全世界で語り継がれそう [686538148]
- 自閉症が「んなっしょい」と連呼するお🏡
- FGOで好きなサーヴァントがアビゲイル、北斎、楊貴妃なんだが
