関数型プログラミング言語Haskell Part32

■ このスレッドは過去ログ倉庫に格納されています
2019/01/29(火) 09:05:47.90ID:gJP/u7IJ
関数型プログラミング言語 Haskell について語るスレです。

haskell.org (公式サイト)
https://www.haskell.org/
日本Haskellユーザーグループ
https://haskell.jp/

前スレ
関数型プログラミング言語Haskell Part31
https://mevius.5ch.net/test/read.cgi/tech/1506447188/
2019/02/16(土) 07:21:27.63ID:6iOnrs/B
スレを読み直してて気づいたけど、>>60ってこういう意味で言ってたのね

もちろんそのように(>>57の前半のように)考えてる
fact 0 = 1の結果はすぐ(fact n = n * fact(n - 1)に)反映されるんじゃないの?
2019/02/16(土) 09:09:45.75ID:pHmZSgK3
もういいだろう ただ単に基本的文法すら知らない子じゃん
2019/02/16(土) 13:13:23.08ID:aQjbCKoN
とっつきにくいも聞き飽きたな
パワハラ上司に同じこと言えるのかと
本当にとっつきにくい相手はそういう輩だ
2019/02/16(土) 13:16:38.83ID:CJGMkJvN
ややこしいことをややこしい方法で簡単にするのがhaskell
2019/02/16(土) 14:01:52.10ID:aQjbCKoN
Pythonのように型を書かないやつはゴミクズ
とかいうハラスメントが一番の問題だから遅延評価は誤差の範囲内
151デフォルトの名無しさん
垢版 |
2019/02/17(日) 00:52:21.04ID:jxnSJIL4
一回しか変数に代入しない場合は副作用になりますか?
YES か NOでお答えください。

JavaScriptで言えばこういうコードです。
const a = foo(), b = bar(a), c = baz(b);
(const変数は再代入ができません)
152デフォルトの名無しさん
垢版 |
2019/02/17(日) 00:52:52.45ID:KFkN1Yft
Haskellスレの皆さんこんにちは✨😃❗
突然ですがこのたびWeb制作板JavaScript質問スレにて、スレ民の総意により、
[1,2,3].map(v => (v += 2, v * v));
のv += 2は副作用ではない。
と決定しました!
ありがとう!ありがとう!
2019/02/17(日) 00:55:14.71ID:jxnSJIL4
>>152は再代入と(再代入しない)代入の違いがわからず
代入は副作用であると言い張っているマヌケが
再代入の例を出し、代入は副作用であると
結論づけようとしているだけなので無視してください。
154デフォルトの名無しさん
垢版 |
2019/02/17(日) 01:04:11.22ID:KFkN1Yft
>>153
?別の方と勘違いされているのでは??
話はシンプル。質問をして、その答えを得た。以下が全てです。この質問と答えに、前後の文脈など関係ありますか??

904 Name_Not_Found sage 2019/02/17(日) 00:42:09.09 ID:???
>>901
悪いけど以下の(ア)に入るのは1か2か答えてくれる?1か2の一文字書くだけだから出来るよね?
[1,2,3].map(v => (v += 2, v * v));
のv += 2は(ア)である
1. 副作用である
2. 副作用ではない

907 Name_Not_Found sage 2019/02/17(日) 00:44:40.52 ID:???
>>904
Wikipediaの2つの成立条件を考えれば、2. は迷惑だろ

908 907 sage typo 2019/02/17(日) 00:45:33.97 ID:???
× 2. は迷惑だろ
〇 2. であることは明白だろ
2019/02/17(日) 01:06:42.19ID:jxnSJIL4
あの?Haskellスレを荒らさないでくれますか?
関係ない話はJavaScriptスレに戻ってください
156デフォルトの名無しさん
垢版 |
2019/02/17(日) 01:13:02.79ID:KFkN1Yft
>>155
おや?
>>151を書き込んだのはどなたですか?w
何か都合の悪いことでもあったのですか?w
大慌てで>>151を張りに来たようですが?w
2019/02/17(日) 01:15:49.49ID:jxnSJIL4
>>151は単なる質問です。
158デフォルトの名無しさん
垢版 |
2019/02/17(日) 01:25:17.93ID:KFkN1Yft
フフッw
2019/02/17(日) 01:47:05.17ID:bP6HzLuJ
うるせ〜〜〜〜一生代入してろ
160デフォルトの名無しさん
垢版 |
2019/02/17(日) 03:04:30.74ID:lVDDSVXk
Haskellスレ民の方々どうも!
Web制作板JavaScript質問スレにて、
https://en.wikipedia.org/wiki/Side_effect_(computer_science)
の以下の文章について…
> One common demonstration of side effect behavior is that of the assignment operator in C++.
副作用の振る舞いの一般的なデモとしては、C++の代入演算子があります。
> For example, assignment returns the right operand and has the side effect of assigning that value to a variable.
例えば代入は右オペランドを返し、かつそれと同じ値を変数に代入するという副作用を持ちます。


スレ民の叡智を結集した結果、

・C++の代入演算子は副作用があるが、JavaScriptの代入演算子は副作用がない

・[1,2,3].map(v => (v += 2, v * v));
のv += 2は主作用を使っているのであって、副作用など使っていない!

と決定しました!
パチパチパチ〜
ありがとー!!
2019/02/17(日) 13:09:25.08ID:C3KvaR2D
初期化と代入の違いはC++でさんざんやったやつだろ
C++には遅延評価がないから余裕じゃないのか
162デフォルトの名無しさん
垢版 |
2019/02/17(日) 17:34:05.11ID:HZyuZSmb
runSTという魔法がある
2019/02/20(水) 10:51:29.01ID:FaK+gznk
Cのマクロ
#define fact(n) (((n)==0)?1:(n)*(fact((n)-1))
これだったら一見まともに見えて
実は無限ループする罠

fact(0)は
((0==0)?1:(0)*((((0)-1)==0)?1:((0)-1)*(....
となって無限ループ。
(ややこしいんで括弧の数とか間違って
るかもしれないけど)

C++でインライン関数で定義した場合は
論理式短絡評価で動くかもしれんが
2019/02/20(水) 11:35:48.52ID:FaK+gznk
再帰を含む関数がインライン展開されることを
期待するほうが間違いだったか...
2019/02/20(水) 11:43:51.95ID:KVaXFVJv
スレチ
166デフォルトの名無しさん
垢版 |
2019/02/20(水) 16:55:25.36ID:xw22aw45
テンプレートメタプログラミングでもしてろクソ
2019/02/22(金) 10:09:30.67ID:ioyynd1U
花粉の時期に入るとみんなこれやり始めるよね
2019/02/22(金) 19:18:12.74ID:ioyynd1U
だめだわからん

fold_left :: (a -> b -> a) -> a -> [b] -> a
fold_left _ a [] = a
fold_left f a (x:xs) = fold_left f (f a x) xs

リストが a1 a2 a3のとき

folder_left f (f a a1) [a2 a3]
になることはわかる

その先の展開が何時間考えてもわからん
f(f(f(a,a1),a2),a3)になるってゆーんだが
イメージに繋がらない

お前らこんな難解なの本当に使いこなせてるの?
ここまでわかりにくいと有用なのか疑わしく思えて来る
2019/02/22(金) 19:43:58.95ID:LKaW/yz7
>>168
foldlなんて単なるループみたいなもんだし
今どきJavaでもやるくらい

分かるまでは変に抽象化しないで、具体例で考えるといいよ

folder_left f a [a1 a2 a3]
じゃなくて
folder_left (+) 0 [1, 2, 3]
で考えるとか
そしたら
folder_left f (f a a1) [a2, a3]は
folder_left (+) ((+) 0 1) [2, 3]になる

要は最初に
int sum = 0
for(int a : xs) sum = sum + a

と書くのと変わらない
sumへの蓄積を、変数への再代入ではなく次の関数への引数として書いてるだけ

どちらかというと、いわゆる関数型っぽいのはこういうのよりfoldrでリスト作ったりするときの方かな
2019/02/22(金) 19:47:35.11ID:ioyynd1U
>>169
まったくわからない
例題載ってるとこにも似たようなことは書いてあるんだけども

ループで書くならすぐ終わる話だけど
ややこしすぎてイメージがつかめない
イメージがつかめたらその時点で理解終了なんだけど
2019/02/22(金) 19:51:15.80ID:ioyynd1U
a2とa3が分離されそうなことはわかるんだけども

folder_left f (f a a1) [a2 a3]
      ^^^^

こいつがどこ行くのっていうのと
どこをどうやったら()で括られることになるのかイメージできない
2019/02/22(金) 20:17:22.94ID:LKaW/yz7
>>171
folder_left f (f a a1) [a2, a3]
になるところまではわかるんだよね?
そしたらまず括弧の中から先に計算するのはどの言語も普通だよね
だから先に(f a a1)の答えが出る
fは引数を2つとる関数だから、答えを出すのに支障はないよね
ここで(f a a1)の計算結果をz1としようか
そしたら上の式は
folder_left f z1 [a2, a3]になるよね?
そうすると、f、z1、[a2, a3]の3つの引数を使って、folder_leftがまた呼び出されるのがわかる?ここが再帰ね
folder_leftの定義は2つあるけど、[a2 a3]は空リスト([])じゃないから、下の
folder_left f a (x:xs)の方が呼ばれるよね?
ここでaはz1、xはa2、xsは [a3]だよね
だからベタで書くと
folder_left f (f z1 a2) [a3]になるよね?
同じように括弧の中が先に計算されるから、(f z1 a2)をz2としようか
そしたら
folder_left f z2 [a3]となる
また全く同じようにfolder_leftを呼び出すと、次は
folder_left f (f z2 a3) []となる
そして同じように(f z2 a3)をz3とすると、
folder_left f z3 []と書ける
ここでまたまたfolder_leftを呼び出してるわけだけど、最後のリストが空リストだよね
だからfolder_leftの2つの定義の内、上の方のfolder_left _ a [] = aが呼ばれる
上から順に呼び出し条件を見てるからね
ここでaはz3のことだから、最終的にz3が答えになる
じゃあz3が何かっていうと、(f z2 a3)だよね。そしてz2が何かっていうと、(f z1 a2)だよね
つまりz3は(f (f z1 a2) a3)のことだ
そして最後にz1は(f a a1)だから、結局
z3 == f (f (f a a1) a2) a3となる
これでどうだ
2019/02/22(金) 20:22:50.89ID:ioyynd1U
>>172
()の中って完全に展開されるまで実行されないものと思ってた
例題もそんな書き方だったし

これならわかる!
ありがとう
2019/02/22(金) 20:30:54.11ID:LKaW/yz7
>>173
そこらへんは評価戦略の話であって別件だね
再帰の本質ではないよ
Haskellといえば遅延評価みたいなところがあるから混乱しやすいけどね

上で言うならz3こと(f (f (f a a1) a2) a3)を、最後までこの形で持って行って、最後にまとめて計算するのが遅延評価
上で書いたみたく適宜評価していくのが正格評価
Haskellだとfolder_leftは二種類あって、
遅延評価版がfoldl
正格評価版がfoldl'
ぶっちゃけ左畳み込みに関してはfoldlを使うことはない
全部foldl'でいい
2019/02/23(土) 00:41:48.52ID:RiBir1w3
カリー化関数の意図がわからん

sum_of :: (Integer -> Integer, Integer, Integer) -> Integer
sum_of (f, n, m)
| n > m = 0
| otherwise = f n + sum_of (f, n + 1, m)

これはわかる

sum_of' :: (Integer -> Integer) -> Integer -> Integer -> Integer
sum_of' f n m
| n > m = 0
| otherwise = f n + sum_of' f (n + 1) m

どう見ても書き換えただけにしか見えないんだけどこれ意味あって書いてるのかな
カリー化って引数可変で動作する関数を定義するためのものって理解したけど
後者にはそんな意図が含まれてるように見えない
2019/02/23(土) 02:34:37.24ID:hS0A7KKk
>>175
やってるのは数式で書くと Σ[i=n..m] f(i) か
再帰をちょっと具体的に書き下さないと何のsumかわからんかった

それで多分やりたいのは
こういう風に個別の総和関数が手軽に作れますよみたいな話だと思う
タプルで定義されてるとこういう風にはいかない
(書けないことはないけどめんどくさい)

sumOfTwice :: Integer -> Integer -> Integer
sumOfTwice = sum_of (*2)

ここで(*2)とかできるのも
(*) :: Integer -> Integer -> Integer
がカリー化されてるおかげ
こういうのを部分適用と言って可変長引数とは異なる概念
2019/02/23(土) 02:59:05.43ID:RiBir1w3
>>176
(*2)の意味わからなくて前後調べたら演算子をカリー化できるとかあって
やっと意味わかったありがとう

しかも例題の先の先の方に有効な利用法書いてあったけど
なんかどうもサイトの進め方と合わないなー・・変えるかー
こんなこと書いてもなんか意味あんのだから何なんみたいな悶々パターンが多すぎる

とても簡単ですとか書いてあったら相当難しいフラグ確定
考え方が違うんだろうな
2019/02/23(土) 06:50:54.90ID:T/+XuHA6
考え方を変えるのが関数型を学ぶ一番の目的だと思うけど、
合わないなら関数型あきらめればいいじゃん。
うちは論理型言語に全く馴染めなくて、それに時間使うのやめた。
2019/02/23(土) 10:50:43.56ID:7gjHPQsv
そうじゃない
人を信じるのをあきらめて嘘を嘘と批判する
とても簡単ですと言った奴は嘘つきのクズであると
2019/02/23(土) 13:04:48.43ID:RiBir1w3
しかしいいサイト全然ないなどうしたもんか
お前らどうやって習得したのよこんな難解な言語
2019/02/23(土) 13:35:58.14ID:7gjHPQsv
例えばC#とF#の考え方は変わらないし
考え方を変えるというのも嘘だな

嘘に気付くのに1日かかるやつと5年以上かかるやつの差は大きい
2019/02/23(土) 14:01:38.38ID:E9HQXzXo
>嘘に気付くのに

ひどい世の中だな
2019/02/23(土) 17:11:04.23ID:RiBir1w3
Prelude> let foo n = ¥x -> x * n
Prelude> :t foo
foo :: Num a => a -> a -> a
Prelude> let foo10 = foo 10
Prelude> :t foo10
foo10 :: Integer -> Integer
Prelude> foo10 10
100
Prelude> foo10 20
200

Prelude> let foo100 = foo 100
Prelude> foo100 10
1000
Prelude> foo100 20
2000

Prelude> let foo5 = foo 5
Prelude> foo5 10
50
Prelude> foo5 20
100

Prelude> :t foo (1.234 :: Double)
foo (1.234 :: Double) :: Double -> Double
2019/02/23(土) 17:12:26.05ID:RiBir1w3
>>183のクロージャの説明がさっぱりわからない

関数を生成する関数を簡単に作ることができるって言ってるんだけど
やってることは定義を繰り返してるだけでちっとも生成してない
どういう意味で関数を生成したって言ってるんだろ・・
Stringで関数生成してevalで評価しましただったらわかるんだけど、これ違うよね
それともhaskellの場合は関数定義は関数生成としているのか・・わからん
一体これは何が言いたいのか・・

実はどうでもいいことで気にしなくてもいいなら納得するんだけども
2019/02/23(土) 17:31:29.38ID:YUL1Jv8G
前スレに比べて明らかに初心者が多いのは何故だ
186デフォルトの名無しさん
垢版 |
2019/02/23(土) 17:37:12.35ID:5fn4St+r
またHaskellのせいにしてるの?
以下は同等のJavaScriptだけど。
let foo = n => x => x * n;
let foo10 = foo(10);
foo10(10);
//=> 100
foo10(20);
//=> 200
let foo100 = foo(100);
foo100(10);
//=> 1000
foo100(20);
//=> 2000
let foo5 = foo(5);
foo5(10);
//=> 50
foo5(20);
//=> 100

てか何の言語なら知ってるんだっけ?
2019/02/23(土) 17:46:51.51ID:RiBir1w3
>>186
そうじゃなくてこれ関数定義だけで生成なんかしてないよね?って話
ぱっと見パスしてもいいようなどうでもいいことにも見える
そうであれば次に行く

どうもHaskellは納得いかないことがあまりにも多いんだ
文化の違いなのか考え方の違いなのかわからんけど

CかObj-CかSmalltalk-80/VisualWorksで
188デフォルトの名無しさん
垢版 |
2019/02/23(土) 17:59:11.82ID:5fn4St+r
Cは実行時関数生成能力ないから仕方ないけど…

let foo10 = foo 10
は関数を返す関数fooに10を渡して、
関数(¥x -> x * 10)を得て(これが、ここが「生成」)
それにfoo10って名前を付けてるって理解は無理?
あなたこれまでに¥x -> x * 10って関数定義した覚えある?書いた覚えがあるのは¥x -> x * nでしょ?
まあ次行け次。
2019/02/23(土) 18:05:45.67ID:RiBir1w3
>>188
foo10は結局のところ ¥x->x*n を呼び出してるだけじゃないの?
¥x->x*10って関数を生成してないよね?

そういうことではない?
2019/02/23(土) 18:08:48.44ID:7gjHPQsv
C++だったらtemplate引数として渡したら定義で、コンストラクタに渡したら生成
静的と動的がわかるのが前提だからわからないならpythonかjavascriptから始めるべき
2019/02/23(土) 18:12:36.80ID:RiBir1w3
>>190
PythonならBlenderで頂点やマテリアル抽出するときに必須だったから使ったことあるけど
インデント縛りで胃が溶けそうだった
正直もうやりたくない・・
192デフォルトの名無しさん
垢版 |
2019/02/23(土) 18:18:49.99ID:5fn4St+r
>>189
> foo10は結局のところ ¥x->x*n を呼び出してるだけじゃないの?

Prelude> foo10 10
100
とかのこと言ってるんなら
let foo10 = foo 10
で生成した関数(¥x -> x * 10)を呼び出してるつまり
(¥x -> x * 10) 10
100

> ¥x->x*10って関数を生成してないよね?

してるよ
let foo10 = foo 10 の foo 10の部分で。
(生成のタイミングは今回置いとくとして)
2019/02/23(土) 18:28:43.67ID:RiBir1w3
>>192
わかった!
無名関数で定義されてるからできるってことかー
納得できたありがとう

次行ってみる
2019/02/23(土) 18:29:48.03ID:7gjHPQsv
templateとコンストラクタとメソッドの考え方
関数と関数と関数の考え方
変わったのは見た目だけ
2019/02/23(土) 18:33:42.53ID:RiBir1w3
>>194
C++は全く知らないのでそっちはなんとも
2019/02/23(土) 18:51:02.51ID:RiBir1w3
早速詰まった何を言ってるのかわからん

一般に、関数を呼び出す場合、関数を評価するための環境は空リストです。
最初に、引数がこの環境に追加されます。let で定義される局所変数もこの環境に追加されます。
もしも、環境に該当する変数が存在しない場合は大域変数を参照します。

たとえば、foo 5 と呼び出すと環境は次のようになります。

foo 5 ==> 環境 : [(n, 5)]

ghciで実行

Prelude> let foo n = ¥x -> x * n
Prelude> foo 5

<interactive>:2:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
Prelude>

そりゃそうだよねぇ・・
なんなんだろう何が言いたいのかさっぱりわからない
本当にこんな説明でみんな理解してったの?
2019/02/23(土) 19:26:38.79ID:hS0A7KKk
>>196
そこクロージャの説明のとこでしょ? 読み飛ばしていいと思うよ

手元にHaskellの入門書何冊かあるけど目次や索引にクロージャ無いし
純粋関数型言語でありデフォルトで関数がカリー化されているHaskellに
クロージャとかいう概念は別に要らないと思う
部分適用便利だねってことがわかればおk
2019/02/23(土) 19:34:16.40ID:RiBir1w3
>>197
そっかわかったありがとう!
関数の合成もすぐわかったのでさらに次行ってみる
2019/02/23(土) 20:14:35.45ID:RiBir1w3
データ型の定義まで来た
なんというかやっぱりこのサイトこれからhaskell入門の人にはどうでもいい余計なこと書きすぎなんじゃ・・
と思った
2019/02/23(土) 21:08:00.52ID:RiBir1w3
do構文がIO型だからこのように書ける・・というのがどうもしっくりこないけど
都合上こうするしかなかったってだけの話で特別な意味はないのかな

calc :: IO ()
calc = do
putStr "Input Integer1 > "
x <- readLn :: IO Integer
putStr "Input Integer2 > "
y <- readLn :: IO Integer
let a = x + y
b = x - y
c = x * y
d = x `div` y
n1 = show x
n2 = show y
putStrLn (n1 ++ "+" ++ n2 ++ "=" ++ show a)
putStrLn (n1 ++ "-" ++ n2 ++ "=" ++ show b)
putStrLn (n1 ++ "*" ++ n2 ++ "=" ++ show c)
putStrLn (n1 ++ "/" ++ n2 ++ "=" ++ show d)
2019/02/23(土) 21:24:41.95ID:24PtBhaW
>>200
いちいち躓いたところで立ち止まらない
これは別に関数型がどうとかに限った話じゃなく、未知のジャンルの勉強の話
まず思考を殺して30回読み返す
学ぶは真似ぶから始まる
2019/02/23(土) 21:25:53.99ID:RiBir1w3
納得しないと進まないタイプなので
2019/02/23(土) 21:31:22.65ID:24PtBhaW
>>202
じゃあモナドとflatMapを理解しきってからdo構文に進んでください
それ以外にないです
2019/02/23(土) 21:37:05.47ID:wr+1lm8V
読んでいるサイトが悪いのではないかなあ
すごいH本とか
HaskellではなくてOcamlだけど浅井『プログラミングの基礎』とかを読んだ方が
良いレベルだと思う
2019/02/24(日) 01:39:36.53ID:qI0VELUi
>>200
do は (>>=) の糖衣構文 (=分かりやすく見やすくするための別記法) なので最終的にはモナドと (>>=) を理解するまではしっくりこない。

https://qiita.com/saltheads/items/6025f69ba10267bbe3ee
2019/02/24(日) 01:52:29.83ID:BExwBIrb
最終的に>>=演算子オーバーロードを理解する頃には難易度がC++と同じ
2019/02/24(日) 11:45:28.69ID:mBeDvEXM
>>205
そういうことなら先に進んでもよさそう
リンク先の見たら変換可能なこともわかった
ありがとう!
2019/02/25(月) 13:11:14.94ID:EIUHHo5S
haskellのGUIは何が主流なの
gtkじゃネイティブUIに見えないからqtahとか?
もしくはhaskellではGUIを扱わないとか?
2019/02/25(月) 21:33:28.52ID:jyEH5AtM
趣味でやってるが Threepenny 使ってる
簡単に組み合わせられるようになるかなと
Elm も学習中
2019/02/26(火) 21:42:21.10ID:DUz4HSDe
書籍「Thinking with Types」の第1章をサンプルPDF版で読んでいるのですが、
19ページ目の Exercise 1.4-i でつまずいています。

数式 (a^b)^c と a^(b*c) が等しいことを Curry-Howard isomorphism を使って証明する問題ですが、
これは、

to :: (b -> c -> a) -> (b, c) -> a
from :: ((b, c) -> a) -> b -> c -> a

という型の Haskell の関数を見つけよ、と言うことですよね。
しかし、問題文に書かれている

to . from = id
from . to = id

の意味が分かりません。

to . from の型も from . to の型も共に id の型とは等しくないと思うのですが・・・
2019/02/26(火) 21:57:34.53ID:PosTOau2
to :: (b -> c -> a) -> ((b, c) -> a)
from :: ((b, c) -> a) -> (b -> c -> a)
2019/02/27(水) 01:02:26.71ID:2D6fGXPQ
Haskellにはファーストクラス多相関数がないから
idの型は単相なんだろう
単相のidという名前の同音異義語がちょっと多すぎるだけ
2019/02/27(水) 02:05:02.68ID:kdg0sG7A
>>209
思い出して今日発売のelm本、買おうかなと思ったら尼で売り切れててワロた。
2019/02/28(木) 17:06:29.75ID:W9NOQ7xg
下記の2つの関数の rank について
関数 f は rank 2、関数 g は rank 3 で合ってる?

f :: a -> (forall b. b -> c)
g :: a -> (forall b. b -> c) -> d
2019/03/03(日) 20:55:07.64ID:/obVPbHS
>>212
やっと意味が分かりました。
ありがとうございした。
2019/03/03(日) 22:40:24.54ID:iXSrdfon
条件を満たす限り畳み込むfoldWhileみたいな関数がないのはなぜ?
scanとtakeWhileで出来なくもないけど無駄なリストが生成されちゃうよね
2019/03/04(月) 10:06:50.76ID:P5wfz8lO
scanした後はlast.takeWhileとかだと思いますがfusionされるので作られません
2019/03/04(月) 11:18:43.16ID:yQsTNF7X
>>217
ありがとうございます
fusion調べてみます
2019/03/09(土) 09:51:28.74ID:KBqn1KqM
haskell入門ほぼ読んだけどちょっと物足りなくてもうすこしhaskell勉強したい欲がある(目的は競プロとか月並みにaiとか)
なんかええ本ある? 数学の高速なライブラリとか圏論、モナドの解説あるやつで(数学は拒絶反応しない)
get programming with haskellとか並行並列とか多少気になってるけどどう?
2019/03/09(土) 10:30:48.34ID:Vn/el/At
初心者を抜けた後、実践へ進みたいのなら幾つか勧められる本はある。

しかし、更なる勉強がしたいのなら、勧められる本はない。
初心者用か、初心者を抜けたばかりの者にはまだ難しい本しかない。
特に君の目的(競プロやAI)に叶う本は今のところ皆無だ。

なので、ネットを漁れ。

あと質問がやや曖昧で、何を求めているのか分からん。
数学の高速なライブラリの何を求めてる?
それを自作できる知識なのか?
活用する知識なのか?
もしくは、仕組みが知りたい具体的なライブラリでもあるのか?

圏論やモナドにしても然り。
それらの何が知りたいのか具体的に言ってみ。
2019/03/09(土) 11:02:47.64ID:KBqn1KqM
>>220
具体的には数学書のような理論本ですね 今のところ全然数学臭さがないので(コンピュータとは乖離してるかもしれないけど)
速度に関しては、命令型の書き方でないのでどうすれば速度が出る書き方が出来るかが一番興味あります
ai,競プロはやるとしたときの足掛かりが気になりました
このみっつのどれかが掘り下げられれば幸いです。
2019/03/09(土) 11:19:03.37ID:SKFKP+LU
THUNKとかWHNFとかだろうけど
俺もここら辺の本とかあるなら読んでみたい
2019/03/09(土) 11:28:44.92ID:Vn/el/At
>>221
「数学書のような理論本」 悪いが意味が分からん。
具体的に「何が知りたいのか」を言ってくれ。
理論と言うのが大雑派すぎる。

速度を上げる方法を学びたいのなら、
・Haskell High Performance Programming
・関数プログラミング 珠玉のアルゴリズムデザイン
この2つが正にうってつけだが、
「Haskell入門をほぼ読んだ」段階では挫折しそう。

AI や競プロは前レスでも言ったが本は無い。
AI は reinforcement leaning や deep leaning など技術範囲を絞ったワードと
haskell を組み合わせたキーワードでネット検索。

競プロは実際の競技で提出されたソースをたくさん読んで真似しろ。
2019/03/09(土) 11:50:40.66ID:KBqn1KqM
>>223
どうもありがとうございます。図書館で覗いてみます
具体的には、数学との関わりを体系だって書いてる書籍を探してましたが、そりゃ個々のキーワードで探す方が手っ取り早くて色々漁れますわな
2019/03/09(土) 13:09:34.75ID:HqfcKPNw
競プロにHaskellはどうなんだ…?
良くわからんけどSTモナド使いまくる感じになるのかな
あるいは珠玉のアルゴリズムを理解仕切った超人達の集まりなのか
2019/03/09(土) 13:43:47.24ID:w1EXpOnc
>>221,223
珠玉のアルゴリズムデザインへの入門としては同じ著者の
『Haskellによる関数プログラミングの思考法』
(旧版名は『関数プログラミング入門 ―Haskellで学ぶ原理と技法―』)
がいいと思う
他の入門書よりは数学色が強いし
等式変形によって効率を改善していく運算も割と丁寧に扱っていると思う

あとは『純粋関数型データ構造』とかも参考になるかも?
ただ競プロならSTRefとかSTUArrayとかに習熟するほうが
手っ取り早いし有力かも
2019/03/09(土) 13:49:45.09ID:Vn/el/At
>>225 >>226
例えば AtCoder の参加者のコードを見てみると分かるが、
STモナドなんて使ってるヤツはいない。
そもそも、haskell に慣れたら、STモナドなんて使いにくいだけだろ。
競プロみたいな短く速いコードを書く必要があるなら尚更。

珠玉本を理解しきった者かどうかは知らんが、
極端に短いコードで解いてくるヤツは、
どちらかといえば数学の知識が豊富なんじゃないかな。
問題文を数学の世界に落とし込む事に長けているように見える。

コンテストにもよるが、競技プログラミングは
個人的にはアルゴリズム力よりも数学力がより大事だと思ってる。
例えば Project Euler の高番号問題をシンプルに解けるヤツは競技も強そう。
2019/03/09(土) 15:47:05.82ID:KBqn1KqM
>>226 >>227
どうもありがとうございます。StateとかSTは内部処理はよくわからないけど便利なので使い方おぼえておきたいとこですね
2019/03/09(土) 20:50:02.63ID:2ErVpr0y
珠玉本難解すぎる
登場する学生達が天才過ぎる
2019/03/10(日) 04:06:11.50ID:0rKUQSsg
>>229
それでも理解したいのなら質問すればいい
2019/03/14(木) 01:49:52.87ID:pUnQtnNt
instance head ってよく聞くけど、
これは instance 宣言のどの部分のこと?

例えば次の宣言の場合
instance (Foo a) => Bar (Baz a b) | a -> b where

・(Foo a)
・Bar (Baz a b)
・Bar (Baz a b) | a -> b
・instance キーワードと where キーワードの間の全部
・その他

どれ?
2019/03/14(木) 02:00:29.34ID:pUnQtnNt
>>231
すまん、instance 宣言に関数従属は無いよな。

改めて、

instance (Foo a) => Bar (Baz a) where

この例だとどこが instance head なんだ?
2019/03/14(木) 08:32:21.91ID:pUnQtnNt
>>231
自己解決した。

instance head は => より右側かつ where より左側の部分だった。

スレ汚してすまない。
234デフォルトの名無しさん
垢版 |
2019/03/20(水) 22:23:43.02ID:GM5azBbl
HaskellのGUI(Gtk2hs)でカウンター作ってみた。

import Graphics.UI.Gtk

main = do
initGUI
window <- windowNew
set window [windowTitle := "counter", containerBorderWidth := 10]
mainbox <- vBoxNew True 5
containerAdd window mainbox
label <- labelNewWithMnemonic "0"
boxPackStart mainbox label PackNatural 0
countbtn <- buttonNewWithLabel "Count"
clrbtn <- buttonNewWithLabel "Clear"
boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0

widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI
235デフォルトの名無しさん
垢版 |
2019/03/20(水) 22:24:12.70ID:GM5azBbl
label <- labelNewWithMnemonic "0"
boxPackStart mainbox label PackNatural 0
countbtn <- buttonNewWithLabel "Count"
clrbtn <- buttonNewWithLabel "Clear"
boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0

widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI
236デフォルトの名無しさん
垢版 |
2019/03/20(水) 22:24:33.45ID:GM5azBbl
boxPackStart mainbox countbtn PackNatural 0
boxPackEnd mainbox clrbtn PackNatural 0

widgetShowAll window
onClicked countbtn (labelGetLabel label >>= \n -> labelSetText label (show (1 + (read n))))
onClicked clrbtn (labelSetText label "0")
onDestroy window mainQuit
mainGUI
237デフォルトの名無しさん
垢版 |
2019/03/21(木) 05:11:02.25ID:EnD5r7yP
コマンドラインでエンターを押すごとに数字が増えていく(Ctrl+C押すまで止まらない)
Haskellコード

main = mapM_ (\n -> print n >> getLine) [0..]


out:
0
1
2
3
4
2019/03/21(木) 22:17:24.35ID:2nCrXVEC
急にどしたんww

gtk2hsのドキュメントがHackageから消えてるのは気のせい?
2019/03/21(木) 22:23:19.66ID:NO+0ze73
なかなかGHC8.8出ないね
2019/03/21(木) 23:42:33.25ID:42YMN3yF
無限ポップアップ上げるやつ現れないとは高尚なスレ
リストで遅延評価使うのがなかなかハスケルっぽい
241デフォルトの名無しさん
垢版 |
2019/03/22(金) 06:11:43.80ID:t/nkQ3ne
一応、カウンターみたいなのは純粋関数型言語には作れない言われてたから、作ってみた。
確かにi++みたいな事は出来ないが、違う方法で参照透明性を確保しつつ実現出来ると実感。
(個人的にHaskellには副作用はあると考えているが、参照透明性は崩れないとも考えている)
2019/03/22(金) 07:23:09.19ID:hntcvuv1
そりゃ副作用はあるよ。
じゃなきゃIO処理できない。

haskell の特徴は純粋な関数から副作用のある関数を呼べないこと。
243デフォルトの名無しさん
垢版 |
2019/03/22(金) 07:32:41.43ID:t/nkQ3ne
うい。
そう言う仕組みになってるくせに、IOな関数も扱いとしては純粋な関数と同じ扱いなのが気に入ってます。
(型に気をつけていれば自然とそうなるし、普通にprint関数と純粋関数を関数合成出来るのが好き)
2019/03/22(金) 07:54:45.66ID:chPt0Ign
純粋関数型言語でカウンタが作れないというのは、
同じ関数を呼び出した結果がカウントアップされるような関数のこと。
pythonで書くとこんな感じ。
>>> def create_counter():
  n = 0
  def counter():
    nonlocal n
    n += 1
    return n
  return counter

>>> counter = create_counter()
>>> counter()
1
>>> counter()
2
245デフォルトの名無しさん
垢版 |
2019/03/22(金) 08:09:16.10ID:t/nkQ3ne
>>244
そうなんですが、純粋関数型言語の場合、その関数を何回呼び出したのかカウントする関数を作るみたいな視点の切り替えで対処するのではと。
つまり自身のファイルを読み込んで自身(counter関数)を

a = counter
b = counter

a = 1
b = 2

に置き換える関数なら作れます。

欲しいのは結果であり、動作ではなく結果が同じなら良いと言う解釈です。
■ このスレッドは過去ログ倉庫に格納されています