トップページtech
1001コメント379KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2006/11/07(火) 21:24:26
haskell.org
http://www.haskell.org/

日本語サイト
http://www.sampou.org/cgi-bin/haskell.cgi
http://shidot.dyndns.org/hs/

過去ログ
関数型プログラミング言語Haskell
Part1 http://pc.2ch.net/tech/kako/996/996131288.html
Part2 http://pc2.2ch.net/test/read.cgi/tech/1013846140/
Part3 http://pc8.2ch.net/test/read.cgi/tech/1076418993/
Part4 http://pc8.2ch.net/test/read.cgi/tech/1140717775/
Part5 http://pc8.2ch.net/test/read.cgi/tech/1149263630/

関連スレは>>2
関連書籍は>>3

・2chの仕様により、行頭の半角スペースは表示されません。
 コードをインデントしたいときは、代わりに または全角スペースを使うことができます。
0657デフォルトの名無しさん2007/02/10(土) 01:35:12
>>653
とりあえずやってみる
classは省略

class X {
  public int hoge( int a, int b ) {
    return a + b ;
  }
}
できた。

class Y {
  public int hoge2( ) {
    //abってa*bのこと?
  }
}
わからん。

class Z {
  public int hoge3(???){}
}
さっぱりわからん

先生わかりません


>>655
去年の12月にJava6がでたばっか
Java7はまだまだ先
クロージャについても、まだ検討段階のはずだけど
0658デフォルトの名無しさん2007/02/10(土) 02:20:33
int hoge2(function a, int b) { return a(b); }
と思えばだいたい OK。

hoge3 を計算すると次のようになる。

hoge3
= hoge2 (hoge 1) 3    (def. of hoge3)
= (hoge 1) 3        (def. of hoge2)
= 1 + 3           (def. of hoge)
= 4
0659デフォルトの名無しさん2007/02/10(土) 02:31:56
>>= (hoge 1) 3        (def. of hoge2)
ここは
= hoge (1 3)        (def. of hoge2)
のほうがわかりやすいな
0660デフォルトの名無しさん2007/02/10(土) 02:56:33
わかりやすい じゃなくて、それは間違い。

hoge (1 3) は hoge という関数に (1 3) という値を食わせることに
なるが、(1 3) という値が意味不明なので、正しく評価できない。
0661デフォルトの名無しさん2007/02/10(土) 03:28:01
>>652
public void setValue( int i ) {
これ、自分で引数にint iって書いてあるように、
実際に渡されているのは、関数じゃなくて返り値のintだお。
0662デフォルトの名無しさん2007/02/10(土) 07:40:23
>>656
これからJavaを新しく学ぼうとする奴は大変だな。
C++でもJavaでも、流行り出した頃に始めると
情報多いし似たようなことやってる人も多いし学習曲線もなだらかで
その後も放っておいても情報が入ってくるけど、
ある程度成熟してからはじめて勉強するのって大変よね。
0663デフォルトの名無しさん2007/02/10(土) 14:52:11
>>653
Haskellは興味を持ったばかりで全く読み取れないですが
こんな感じでよろしいでしょうか?

interface A { int f(int a, int b); }
class B { A a; int b;
B(A a, int b) { this.a = a; this.b = b; }
int f(int n) { return a.f(b, n); }
}
public class C {
static int hoge2(B b, int n) { return b.f(n); }
public static void main(String args[]) {
A hoge = new A() {
public int f(int a, int b) { return a + b; }};
B hoge1 = new B(hoge, 1);
int hoge3 = hoge2(hoge1, 3);
System.out.println(hoge3);
}
}

スレ違いっぽくてすみません。
0664デフォルトの名無しさん2007/02/10(土) 15:41:55
>>663
違う言語だから同じかどうかはっきりとは言えないわけだけど、
意図している記法とは違うと思うよ。
最終的な出力は同じでもね。
0665デフォルトの名無しさん2007/02/10(土) 15:53:03
>>664
Aを二引数の関数、Bを一引数の関数と見ればかなり良く対応していると思うが。
0666デフォルトの名無しさん2007/02/10(土) 16:23:09
>>665
それはカリー化ではない
0667デフォルトの名無しさん2007/02/10(土) 16:34:29
>>666
何が言いたいのか分からん。
>>653は高階関数と部分適用の実演であって、Haskellでは部分適用を
カリー化を利用して行うのが一般的だからそうしているに過ぎないと思ったが。
その気になれば>>663をカリー化された形に書き換えられるだろうが、
それに何か意義があるのか?
0668デフォルトの名無しさん2007/02/10(土) 17:01:53
フレームのきっかけを作ったみたいですみません。
記法はともかく雰囲気があっているか(理解が正しいかどうか)
確かめたかっただけです。

Bのfをinterfaceにしてimplementsすればよりそれっぽかったかな。
06696672007/02/10(土) 17:55:44
>フレームのきっかけを作った
感情的な攻撃をしたつもりはなかった。
そう見えたのなら謝る。投稿内容は無視してほしい。
06706682007/02/10(土) 18:41:28
思い過ごしでしたか。議論の邪魔をしてすみませんでした。
書き忘れていましたが 663=668≠652 です。
あとhoge2の型も作らないといけなかったですかね。
0671デフォルトの名無しさん2007/02/10(土) 19:37:18
>>667
> その気になれば>>663をカリー化された形に書き換えられるだろうが
Haskellで書かれたコードをJavaで模倣したいのかと思ったんだが、
もしそうなら当然模倣できるところは全部模倣すべきだよ。
0672デフォルトの名無しさん2007/02/10(土) 20:53:09
まぁ >>671 の言うとおりだな
0673デフォルトの名無しさん2007/02/10(土) 21:22:01
型チェックは省略。
public class Main {
public static void main(String[] args) {
System.out.println("hoge3 = " + (Integer)new Hoge3().reduce());
}
}

abstract class Closure {
Stack args;
Closure() { args = new Stack(); }
Closure apply(Object o) { args.push(o); return this; }
abstract Object reduce();
}

class Hoge extends Closure {
Object reduce() { return (Integer)args.get(0) + (Integer)args.get(1); }
}

class Hoge2 extends Closure {
Object reduce() { return ((Closure)args.get(0)).apply(args.get(1)).reduce(); }
}

class Hoge3 extends Closure {
Object reduce() { return new Hoge2().apply(new Hoge().apply(1)).apply(3).reduce(); }
}
0674デフォルトの名無しさん2007/02/10(土) 21:28:54
Adopting lazy evaluation strategy is left to the reader.
0675デフォルトの名無しさん2007/02/10(土) 23:10:33
おまんこんばんわ

苦労しながらsin x のテイラー展開の収束性を見るプログラムを書いたw

引数は展開次数nとxなのだが、そのうちの展開次数nだけを[1..10]にマップしたい。
だがその方法が分からんので優しいお方おすえて。

カリーかとやらで第一引数だけをまず展開するんじゃないかと思ったが、うまくいかない。
どこを勘違いしているのかも含めてvipperにも分かるように3行で教えてくれw

module Main (main) where

-- Taylor expansion / Honer's method
sin'' 0 x y = y
sin'' n x y = sin'' (n - 1) x ( 1.0 - x * y / ( (2 * n + 1) * (2 * n) ) )

sin' n x = x * sin'' n (x * x) 1.0

converge_sin n = sin' n 1.0

main = print $ map converge_sin [1..10]


出力
[0.8333333333333334,0.8416666666666667,0.841468253968254,0.8414710097001764,0.84
1470984648068,0.8414709848086585,0.8414709848078937,0.8414709848078965,0.8414709
848078965,0.8414709848078965]

じゃわカリー/~
0676デフォルトの名無しさん2007/02/10(土) 23:27:56
>>675
それでできてるじゃないか。何が不満?
0677デフォルトの名無しさん2007/02/11(日) 00:10:04
>>676
converge_sin n という捨て関数を使っているし、角度の引数xはこの中で固定化されている。
それが不満。
Mapすると同時に、角度xもパラメータとして与えたい。
0678デフォルトの名無しさん2007/02/11(日) 00:16:49
main = print $ map (\n -> sin' n 1) [1..10]
main = print $ map (flip sin' 1) [1..10]
main = print $ map (`sin'` 1) [1..10]
main = print $ map f [1..10]
  where
    f n = sin' n 1

好きなのをどうぞ。
0679デフォルトの名無しさん2007/02/11(日) 00:39:28
>>678 x=1 の部分をxのままに残して、最後に与えたかった。
こんな感じか?

module Main (main) where

-- Taylor expansion / Honer's method
sin'' 0 x y = y
sin'' n x y = sin'' (n - 1) x ( 1.0 - x * y / ( (2 * n + 1) * (2 * n) ) )

sin' n x = x * sin'' n (x * x) 1.0

main = print $ (\x -> map (\n -> sin' n x) [1..10] ) 1.0
0680デフォルトの名無しさん2007/02/11(日) 23:30:38
StateとかIOとかわけわかんねぇ‥‥‥ orz
手続き型に20年安住してしまったので頭固すぎて挫折しそうですパパ。



0681ちっとも理解が進まねぇorz2007/02/11(日) 23:40:59
一定の時間ごとにkeepalive処理(通信)を行いつつサービスをするUDPな
サーバを作るときって、次のどちらが素直な設計になるますか?
ヒント頂けると有り難く。

a: State に全部の通信の状態をくるんでしまい、非同期にkeepaliveする
recvfromあるいはselectでタイムアウト付きのwaitがしたくなる、
が、探しかたが悪いのかやりかたがよくわからない‥‥‥。

b: マルチスレッドで走らせてがんばる
>596のforkIOってオイシイ?
スレッド間での状態の同期ってできるの?

c: そもそもそういう処理をHaskellでやろうと思う方が無茶

d: 俺が馬鹿なだけで、もっと簡単な方法がある
0682ちっとも理解が進まねぇorz2007/02/12(月) 00:19:26
その後軽くググって、beautiful concurrencyなる文書を見つけてみた。
まだレベル1と2の間にの俺にはよくわからない気がするが、明日よんでみよう。
STMってなんじゃらほい。interopの小間使いか(ぉぃ)

0683デフォルトの名無しさん2007/02/12(月) 09:14:29
流れを読まずに質問。

サブディレクトリの中身も取得するgetDirectoryContentsを書いたのだが
どうもコードに無駄があるように思える。

Haskellらしく簡潔に書くにはどう書いたらいいんだ?

--

module GetRecursiveContents (getRecursiveContents) where
import System.Directory
import Data.List

getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents p = do cs <- getDirectoryContents p
                  result <- mapM (getRecursiveContents' p) $ filter (not . isSuffixOf ".") cs
                  return $ concat result

getRecursiveContents' :: FilePath -> FilePath -> IO [FilePath]
getRecursiveContents' p c = do let newPath = mergePath p c
                    dir <- doesDirectoryExist newPath
                    if dir then getRecursiveContents newPath
                       else return [newPath]

mergePath :: FilePath -> String -> FilePath
mergePath a b
  | "\\" `isSuffixOf` a = a ++ b
  | otherwise = a ++ "\\" ++ b
0684デフォルトの名無しさん2007/02/12(月) 09:43:53
>>681
bだろ。
同期を取るには二つ方法があって、MVarという古典的な共有変数を使っても良いし、
STMという仕組みでロックなしに共有状態を操作しても良い。
STMはちゃんと使ったことがないけど、たぶん次のような特徴がある。
・MVarでできることはなんでもできる。
・明示的にロックをエミュレートしたりしない限り、デッドロックを気にする必要がない。
・(どの程度か知らないが)遅い。

詳しくは、リファレンスや、そこからたどれる論文を読んでくれ。
0685デフォルトの名無しさん2007/02/12(月) 12:24:50
あんまり変わらないが
再帰の深さの指定をつける時を考えると、ツリー構造定義する方が早い気がする
import Monad
dirrec :: FilePath -> IO [FilePath]
dirrec p = do
  cs <- getDirectoryContents p
  let paths = [ p' ++ c | c <- cs, not ("." `isSuffixOf` c) ]
  dirps <- mapM doesDirectoryExist paths
  zipWithM dive dirps paths
  where
  p' = addYen p
    where
    addYen "\\" = "\\"
    addYen [c] = c : "\\"
    addYen (c:cs) = c : addYen cs
  dive False = return
  dive True  = fmap concat . dirrec
06866852007/02/12(月) 12:47:59
あ、間違えた
型が合っても動作が違う
  (...)
  fmap concat $ zipWithM dive dirps paths
  (...)
  where
  dive False p = return [p]
  dive True p = dirrec p
0687デフォルトの名無しさん2007/02/12(月) 13:04:43
".",".."だけを特別扱いすれば良いような気がする。

getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents fp
 = getDirectoryContents fp >>= mapM (fx fp) >>= return . concat
 where
   fx :: FilePath -> FilePath -> IO [FilePath]
   fx bp "."  = return [bp]
   fx bp ".." = return []
   fx bp f    = do let np = bp ++ ('/':f)
                   b <- doesDirectoryExist np
                   if b then getRecursiveContents np
                        else return [np]
0688ちっとも理解が進まねぇorz2007/02/12(月) 14:27:04
>684

ありがと。
どうせ同期を取るのは数秒に一回〜1秒に数回程度で、別に遅くてもいいから
STM使ってみるよ。ghc6.2では使えないんだよね。
0689デフォルトの名無しさん2007/02/12(月) 14:28:38
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents fp = liftM concat $ mapM f =<< getDirectoryContents fp
  where
    f "." = return []
    f ".." = return []
    f name = getRecursiveContents path `catch` \e -> return [path]
      where
        path = fp ++ "/" ++ name

doesDirectoryExistが気持ち悪かったので書き直してみたが、
今度は例外を握りつぶしていて良くない。
「inappropriate type」だけ選択的にcatchするにはどうすれば良いんだろう。
0690デフォルトの名無しさん2007/02/12(月) 21:47:25
haskell-mode-2.2 がelisp errorになる
06916832007/02/12(月) 22:38:10
答えてくれた人たちありがとう。
がんばってソース読んでみる。

「あるディレクトリ以下の全てのログファイル
(拡張子固定)をすべて集計」ってのをやりたかったんだが
意外とめんどいコードが要るのな。
0692デフォルトの名無しさん2007/02/12(月) 23:35:19
どちらかといえばHaskellでやる事じゃないな
0693デフォルトの名無しさん2007/02/13(火) 00:04:56
言語としては悪くないんだが、ライブラリがね…
0694デフォルトの名無しさん2007/02/13(火) 00:16:42
>>693
素人は引っ込んでいてもらえますか?
0695デフォルトの名無しさん2007/02/13(火) 00:25:50
>>694
俺が何か間違ったことをいったか?
例えば、getDirectoryContentsにもっと短い名前を与え、
ファイルパス操作関数を用意するだけで、>>683みたいなコードはずいぶん書きやすくなる思うが。
0696デフォルトの名無しさん2007/02/13(火) 00:45:53
短くして何する関数か名前から推測できなくなったらそれはそれで嫌な気が。
よく使うような関数は用意しといてってのには同意。
0697デフォルトの名無しさん2007/02/13(火) 01:07:09
>>695
思った通り素人だ。
CかJavaのプログラマだろうな。
しかも学生。
推測は当たってたか?
0698デフォルトの名無しさん2007/02/13(火) 01:28:02
>>697
うざい
0699デフォルトの名無しさん2007/02/13(火) 01:59:40
>>695=698
気持ちよく書き込んでいたところすまないね。
ここはそういう話をする所じゃないんだよ。
関数名が長いだとか短いだとか、ハンガリアンがどうのこうの、コメントはこうかきましょうだの、
ここの常連はそういう話はとっくに聞き飽きてるの。
07006982007/02/13(火) 02:11:06
>>699
695 ではない.
必要ない書き込みでスレを無駄に消費しているお前がうざいだけ.
これも無駄なレスではあるが.
お前の無駄な書き込みがこのスレから消えてくれることを切に願う.
0701デフォルトの名無しさん2007/02/13(火) 03:22:57
>>700
> これも無駄なレスではあるが.
わかっていて書かずにはいられないとは、リアル厨房か?
どうせ何も本質を理解していないんだろう?
半年ロムってろよ。
0702デフォルトの名無しさん2007/02/13(火) 08:42:38
>>694
2chで「素人は引っ込んでろ」って、馬鹿?
むしろ玄人様が学会にでも行けよ。
0703デフォルトの名無しさん2007/02/13(火) 12:34:09
>>702
興奮してるのと、摩訶不思議な2ch観を持ってるのは十分に伝わってくるけど、
文章全体としては何が言いたいのかさっぱりわからない。
0704デフォルトの名無しさん2007/02/13(火) 13:59:52
>>690
elispもHaskellもよくわからないけど
haskell-indent.el l.319 の :trype を :type にするとエラーは出なくなった
07056932007/02/13(火) 18:44:48
>>699
>関数名が長いだとか短いだとか、ハンガリアンがどうのこうの、コメントはこうかきましょうだの、
俺だってソフトウェア工学の話がしたいわけじゃない。
>>691が言っているような単目的のコードを快適に書き散らすには
関数名の長さは重要だと思っているから、そう書いた。

それから、判り難かったかもしれないが、>>693>>692へのレス。
0706デフォルトの名無しさん2007/02/13(火) 23:02:55
副作用を禁止して型とかの制限機構を入れたLispってことでいいのか?

0707デフォルトの名無しさん2007/02/13(火) 23:36:34
関数型プログラミングしか出来ない(出来るが非常に回りくどい)関数型言語は
結局生産性悪いと思うんだけどどうだろ
Lisp系みたいなマルチパラダイム言語が一番使いやすいなぁ
07086982007/02/13(火) 23:48:28
それを言っちゃあお終いよ
0709デフォルトの名無しさん2007/02/13(火) 23:50:42
>>707
今の段階ではね。
でも、まだ研究が煮詰まってないから何とも言えないな。
0710デフォルトの名無しさん2007/02/13(火) 23:50:43
ど素人が質問するけど、
Haskellでなんちゃらエンジンみたいなの作る場合、
他の言語と比べてけっこういいもんができるそう?
0711デフォルトの名無しさん2007/02/13(火) 23:53:28
Haskellでなんちゃらエンジンを作れる人が他の言語でなんちゃらエンジンを作ると良いものができるんじゃない?
0712デフォルトの名無しさん2007/02/14(水) 00:05:22
言語が違ったぐらいで出来栄えがそんなに変わるかなあ。
とか。
むろんケースバイケースだけども。
0713デフォルトの名無しさん2007/02/14(水) 00:18:33
>>707
Haskellみたいに関数型と手続き型が普通に使えれば十分だと思ってしまうんだが、
そうでもないものなの?
0714デフォルトの名無しさん2007/02/14(水) 01:40:35
普通には使えないと思う
0715デフォルトの名無しさん2007/02/14(水) 02:03:12
ひさしぶりにHaskellをGHCでやってみた
なんでこんなにコンパイル遅いの?
だれのせい?
頭のいい奴がつくってこの出来?
0716デフォルトの名無しさん2007/02/14(水) 02:47:05
>>715
Cコンパイラと比べてないか?
言語仕様がどれだけ複雑か考えただけでも遅くなるのは当然だろ
0717デフォルトの名無しさん2007/02/14(水) 02:56:37
なんで当然なのか教えてくれ
0718デフォルトの名無しさん2007/02/14(水) 03:10:02
直感
0719デフォルトの名無しさん2007/02/14(水) 03:28:07
>>717
言語仕様が複雑だからだろ。
0720デフォルトの名無しさん2007/02/14(水) 03:52:54
無限リストって怖くね?
0721デフォルトの名無しさん2007/02/14(水) 03:57:33
OCamlと比べてもコンパイルが遅いのは遅延評価とかモナドとか型クラスとかのせいですか?
0722デフォルトの名無しさん2007/02/14(水) 06:16:39
コンパイルの遅さよりもバイナリのでかさの方が問題だ
0723デフォルトの名無しさん2007/02/14(水) 06:24:24
D は言語仕様複雑だけど速い。
要は、

・ 言語仕様が高速なコンパイルに向いているかどうか
・ 最適化をどのくらいやっているか
・ コンパイラのコードが洗練されているか

とかの問題。
0724デフォルトの名無しさん2007/02/14(水) 09:45:34
>・ 最適化をどのくらいやっているか
>・ コンパイラのコードが洗練されているか

はともかく

> ・ 言語仕様が高速なコンパイルに向いているかどうか

は、高速なコンパイルができる→機械語との対応が簡単→言語仕様が簡単、
って言わないのかな‥‥

0725デフォルトの名無しさん2007/02/14(水) 10:34:11
人間にとっての容易な仕様と、コンパイラにとっての容易な仕様は別物、
ってことじゃないかなぁ。

Dの場合、「コンパイラ実装に優しい言語仕様」というのをはっきり掲げてるわけだけど、
それは通常の会話に出てくる「シンプルな言語仕様」というのとは、指しているものが
だいぶ異なっているような気がする・・・。
0726デフォルトの名無しさん2007/02/14(水) 11:27:04
まあコンパイルなんてふつうは遅いものじゃん。
スクリプト言語みたいに実行できるDが異常
0727デフォルトの名無しさん2007/02/14(水) 21:24:06

おい、カスども聞いてくれ
ようやくまともにHelloWorldが書けるようになった高卒の俺が
圏論勉強してみっかーと思ってWikipedia読んでみたんだ
http://ja.wikipedia.org/wiki/%E5%9C%8F%E8%AB%96

アホだろこの説明はw
翻訳がおかしいというか、書いてる奴が説明する気ゼロなんだよ

そもそも「圏論」とか書くから難しそうなんだ
「カテゴリー論」にすれば、すっげー簡単そうなイメージになるのに

あと「圏」のページでは「定義域」、「余定義域」とかいう意味不明な用語がでてくるが、
「射」のページでは「ドメイン」、「コドメイン」と翻訳してある
用語を統一してないのはWikipediaの特性上しょうがないけど、
ドメインって訳したほうが100倍イメージしやすいよな

円周率を3とするよりも、3.14として難しくしたほうが、学習上、良いのはわかる
けど、圏論の説明はあまりにもひどすぎる
頭が悪いとしか思えない

ということで、AAで圏論 Coming soon!
0728デフォルトの名無しさん2007/02/14(水) 21:59:17
数学の専門用語の和訳には数学の文化があって、
「カテゴリー」みたいな一般的な用語であっても、
専門用語と分かるように難しい言葉を当てることが多い。

一方、情報化学では、カタカナのまま使うことが多いので、
その辺、語感に温度差があるように思える。
"Categories for Working Programmers" みたいなのが
あると、なかなか楽しい気はする。


> AAで圏論 Coming soon!
期待してるぜ!
0729デフォルトの名無しさん2007/02/14(水) 22:11:11
> AAで圏論 Coming soon!
wktk!!
0730デフォルトの名無しさん2007/02/14(水) 22:12:33
数学用語ってかっこいいよな
0731デフォルトの名無しさん2007/02/14(水) 22:45:54
VIPPERの俺様がWEBに転がっている情報処理の2006年3月号で
圏論を勉強してやっているのだが、定義4までは理解できるが、
肝心のモナドが出てくる定義5と6が意味不明だ。

天才エスパーが3行で解説してプラトンのイデア界のモナドに俺を接触させろ!おねがい (ぅふ
0732デフォルトの名無しさん2007/02/14(水) 22:54:40
まずはその定義をここに書くんだ
0733デフォルトの名無しさん2007/02/14(水) 23:09:56
>>732
ttp://www.ipsj.or.jp/07editj/promenade/4703.pdf

浪人の先生 これでございあす。
前半は糞クイズでございやすが、後半がモナド入門でやす。

4と5の間には越えられない壁がw

おねがいするお!
0734デフォルトの名無しさん2007/02/14(水) 23:44:33
>"Categories for Working Programmers" みたいなのが

The Haskell Programmer's Guide to the IO Monad ― Don't Panic
http://stefan-klinger.de/files/monadGuide.pdf
こんなの?
0735デフォルトの名無しさん2007/02/15(木) 00:11:39
>>733
3行で説明するのは俺には無理.

まず定義5.これは実際に手を動かすと見えてくるので,
具体例でやるのが良いと思う.以下はその pdf にもある例.

1. リスト函手
・型 A に対し T A は A のリストを作る:
  T A = [A]
・関数 f :: A -> B に対し T f :: [A] -> [B] は次の関数を作る:
  T f = map f
・μ_X は X 型のリストのリストをならして X 型のリストを作る:
  μ_X = concat
・η_X は X 型の値 x からそれだけからなる [X} 型のリスト [x] を作る:
  η_X = singleton = (:[])

これらを図に代入して,ちゃんと可換になることを確認するよろし.
0736デフォルトの名無しさん2007/02/15(木) 00:18:09
こっちも同様に確認するとμ,ηの雰囲気がより分かるかも.

2. Maybe函手
・型 A に対し T A は Maybe A を作る:
  T A = Maybe A = Just A | Nothing
・関数 f :: A -> B に対し T f :: Maybe A -> Maybe B は
  (T f) (Just a) = Just (f a)
  (T f) Nothing = Nothing
・μ_X は Maybe (Maybe X) を Maybe X にする:
  μ_X (Just (Just x)) = Just x
  μ_X (Just Nothing) = Nothing
  μ_X Nothing = Nothing
・η_X は X の値 x を (Just x) にする:
  η_X x = Just x
0737デフォルトの名無しさん2007/02/15(木) 00:49:19
やっと分かった!
drop 5もreverseもnullも自然変換で、
map succやallは自然変換でないと。
前者は構造のみを扱い、後者は要素が絡んでいることを反映しているのか。

これ考えた奴は天才だな。
0738デフォルトの名無しさん2007/02/15(木) 00:50:21
次に定義6.こっちも具体例が条件を満たすことを確認すると見える.

1. リスト函手.これはありがたみが分かりづらい.
・f* = flatten . map f

2. Maybe函手.
・f* = Just . f

Maybe がこれでハッピーなのは,次の具体例を考えると分かる:
「バッグからアドレス帳を取り出し,
 今日誕生日の人を探し,携帯電話を取得する」
これを関数合成で次のように書けるとうれしい:
 getPhone . findBornToday . getAddressbook
ただ,各関数の自然な型は
 getAddressbook :: Bag -> Maybe Addressboo(もってないかも)
 findBornToday :: Addressbook -> Maybe Person(いないかも)
 getPhone :: Person -> Maybe Phone(もってないかも)
なので合成ができない.そこで,* を使って
 getPhone* . findBornToday* . getAddressbook
と書いてやると型があってハッピー.Haskell ではこれを
 getPhone <<= findBornToday <<= getAddressbook
と書けるようになってる.
0739デフォルトの名無しさん2007/02/15(木) 01:06:12
定義5の可換を具体例で示すことはできた。
が、『μが結合則、ηが恒等元の役割をする』というところがピンとこない。
なにとぞ、悟りの光をお与えください。

0740デフォルトの名無しさん2007/02/15(木) 01:29:09
「結合則」という意味:
 左側の図で上側を通る計算はμを中置記法で書き,
 TμT = T と簡約しないでおくと
  T T T A --> (TμT) T A --> (TμT)μT A
 となる.同様に下側を通る計算は
  T T T A --> T (TμT) A --> Tμ(TμT) A
 となる.これが(任意の A について)等しいのだから,雰囲気は
  (TμT)μT = Tμ(TμT)  …代数で言うところの結合則

「恒等元」という意味:
 右側の図で左側の三角形の真ん中を通る計算は
 ηT = T T と簡約しないでおくと
  T A --> ηT A --> ημT A
 右側の三角形の真ん中を通る計算は
  T A --> Tη A --> Tμη A
 これが恒等写像 id_TA に等しいのだから,雰囲気は
  ημT = Tμη = T  …代数で言うところの恒等元,単位元
0741デフォルトの名無しさん2007/02/15(木) 03:45:58
>>740
dクス 結合法則のほうは分かったw  中置記法が味噌かよwww
中置記法で書くと確かに結合側に見えるw
麻呂は前置記法で書いていたので、どう見ても結合法則ではなく可換を意味しているようにしか
見えなかったでおじゃるw


恒等元のほうは、まだ分からんw
ηだけで恒等元??  (ημ)で恒等元? 
でもサ変と右辺でημとμηでひっくり返っているし

もう3行ばかり解説頼むw
0742デフォルトの名無しさん2007/02/15(木) 07:50:31
>>741
一般に,二項演算 * に対して e が恒等元であるとは
任意の a に対して e * a = a * e = a を満たすことを言う.
μを中置記法で読めば,最後に出てくる式はこれと同じ.
0743デフォルトの名無しさん2007/02/15(木) 09:20:05
>>740
凄い! なんかわかった気になる。
そうか、μをfunctor間の演算とみなせばよかったのか。

ところで>738の例で
Maybe functorがf* = Just . f
とあるけど、これでfindBornToday*が
Addressbook -> Maybe Person
から
Maybe Addressbook -> Maybe Person
になるんだろうか?
fをもちあげないといけない気がするんだが…
0744デフォルトの名無しさん2007/02/15(木) 10:25:48
>>743
そのとおりで,こちらのミス.手抜きをしたのがいけなかった.以下が正しい.

f* (Just x) = Just (f x)
f* Nothing = Nothing
0745デフォルトの名無しさん2007/02/15(木) 10:35:57
ああまたミス.f* (Just x) = f x,f* Nothing = Nothing.起きたばかりだけど寝てくる.
0746デフォルトの名無しさん2007/02/15(木) 18:09:27
lispとどっち勉強するか迷ってます
lispよりも強力なのがhaskellってことでいいのでしょうか?
強力というのは最小限の手間で複雑な処理がかけるという意味で


0747デフォルトの名無しさん2007/02/15(木) 18:40:24
>>746
迷ったなら両方やっとけば。
Lispは風呂敷。なんでもリストでつつんでしまう。良く言えば柔軟。悪くいえば節操がない。
Haskellはディナー用食器セット。テーブルマナーがわかっていれば心地良い。
0748デフォルトの名無しさん2007/02/15(木) 18:56:11
>>747
>Haskellはディナー用食器セット。テーブルマナーがわかっていれば心地良い。
でも調理は自分で、でも何故かアレルギー反応する人がいるのがおもしろい。

0749デフォルトの名無しさん2007/02/15(木) 19:59:31
昨日は詳しい人がいたのね。

HaskellのMonadって、実はKleisliの方が近いんじゃないか、と思うんだけど、
何でMonadと呼ばれているんだろう?

(T,η, *)と(M, return, flip (>>=))が対応してるのに対して、(T, η, μ)とは
間接的にしか対応してないのに。Monadなんて使わなければ関連する定義
も1つ減って幸せな気がする。
0750デフォルトの名無しさん2007/02/15(木) 22:08:19
対象→例えば数字だったり、式だったり、式+式だったり
群  →対象の集まり
圏  →対象と射の集まり

これで認識あってる?
0751デフォルトの名無しさん2007/02/15(木) 22:21:00
モナドは函手の間の演算だってそういうことですか・・・。
0752デフォルトの名無しさん2007/02/15(木) 22:30:13
>>750
数学の用語としてだったら、群は間違ってる。
群は、可逆な演算の定義された集合の事(厳密な言い方でないけど)。
例えば、整数の集合に足し算と引き算を定義すれば、群である。
圏は一応あってると言っていいと思う。
0753デフォルトの名無しさん2007/02/15(木) 22:33:50
可逆という言葉がわからん
集合という言葉の定義がわからん
0754デフォルトの名無しさん2007/02/15(木) 22:39:02
群はモノイドでかつ任意の元に対して逆元が存在するもの。
0755デフォルトの名無しさん2007/02/15(木) 22:40:22
http://ja.wikipedia.org/wiki/%E5%85%AC%E7%90%86%E7%9A%84%E9%9B%86%E5%90%88%E8%AB%96
0756デフォルトの名無しさん2007/02/15(木) 22:48:49
やっぱりボチボチと圏論わかってきてるひと増えてるんだね。
でも、やっぱりよくわからのだがこれ一体なんの役に立つんだ?
■ このスレッドは過去ログ倉庫に格納されています