tamaño de fuente: + - prefijar
RSS 1.0
G a t a  D u r m i e n t e  -  d i a r i o
Volver al índice
Firefox :: Faster Safer Cuter
Say No to corrupt Audio CDs
三次元なんかに興味あるか、ばーか。

Tópicos Recientes

* まもなく移轉
當サイトはまもなく移轉します。

* みっくみく事件の決着
驚いた。ドワンゴが殆ど完全に折れる形で、しかもこんなに早く決着が付くとは思はなかった。こんな結末になるとは夢にも思はなかった。

* Quốc ngữ と日本語
ベトナム語は六つの聲調を持つ言語であるが、現在それを表記する爲に用ゐられてゐる Quốc ngữ ではその六声調を書き分ける事が出來るらしい。

* 自然物と信仰/生體機械としての人間/初音ミク/オープンソース戰爭
みっくみくが JASRAC された件には非常にもやもやとさせられる。だから出來るだけ消化しようと試みた。Every man thinketh his burden is the heaviest.

* HsHyperEstraier 0.1
HyperEstraier の Haskell 用バインディングである HsHyperEstraier を公開した。

Lee más...

_ martes, 6 febrero 2007 Haskell の forall キーワードについて
Cuenta Larga = 12.19.14.0.15; tzolkin = 4 Men; haab = 8 Pax [Trackback Ping]

 Haskell の forall キーワードは途轍もなく難しいし、簡單に讀める資料があまり無い事もあって良く分からなかったのだが、やうやく何とかその尻尾くらゐは掴んだやうに思ふので、その手を離して仕舞はない内に書いて置く。ここに書いてある内容は私の拙い理解に基いてのものであるから、完全に正しいとは確信してゐない。だから、この記事をお讀みになる方にはその點に注意して戴きたい。

型變數のスコープ

mkList :: a -> [a]
mkList x = [x]
 このやうな關數 mkList があるとする。(ここでは型のみが重要なので實裝はどうでも良い。)mkList の型は a -> [a] だが、この例で型變數 a は型全體の中で參照されてをり、型全體が a のスコープになってゐる。と云ふ事はつまり型 a -> [a] が具體化される時には二箇所に現れてゐる a がどちらも同じ時點で具體化されるし、その時は必ず同じ型に具體化される事になる。この事を forall を使って明示的に書くと次のやうになる。forall を使はなかった前者の型は、實は後者の型の省略形に過ぎない。型變數 a は『ランク1の型』だ。
mkList :: forall a. a -> [a]
 forall を使ふ事で、特定の型變數のスコープを次のやうに變更する事が可能だ。この時の型變數 a は『ランク2の型』と呼ばれる。
foo :: (forall a. a -> [a]) -> [Int]
foo f = f 100

引數に多相關數を取る關數

 この關數 foo は、型が a -> [a] であるやうな多相型の關數を多相關數のままで取って引數 100 を渡す。渡された關數が自分の引數に對してどのやうな演算をするかはその關數次第だが、自分に與へられた引數の型を變更せずにそれをリストの中に入れて返す事だけは約束してゐる。だから例へば foo を次のやうに呼び出すと、このプログラムは "[100]" と表示する。
main :: IO ()
main = print $ foo mkList
 一方で、次のやうな呼出しはコンパイルエラーになる。foo は多相關數 a -> [a] を取る事になってゐるのに、mkStrList は具體的に過ぎるからだ。
mkStrList :: String -> [String]
mkStrList str = [str ++ "!"]
main :: IO ()
main = print $ foo mkStrList -- エラー!

普通の關數

 もし foo の型が次のやうになってゐた場合はどうだらうか。
foo' :: (a -> [a]) -> [Int]
 foo' の引數には forall が無いので、foo' の取る引數はもはや多相關數ではなく、foo' の呼出側によって具體化された關數として渡されるやうになる。だから例へば次のやうな呼出しは正當なものになる。foo' の引數として String -> [String] を渡してゐる。
main :: IO ()
main = print $ foo' mkStrList
 では、foo' の方では引數として受け取った關數をどう使へば良いだらうか。受け取ったのは多相關數ではないから、關數 a -> [a] の實際の型を決める權利は foo' には無い。だから次のやうな實裝はコンパイルエラーだ。
foo' :: (a -> [a]) -> [Int]
foo' f = f 100 -- エラー!
 f は foo' にとっては何だか分からない型 a の引數を慾しがってゐるのだが、foo' の型が例へば (a -> [a]) -> a -> [Int] のやうなものでない以上その型の値は手に入らないので、結局渡された f を呼ぶ手段は無い事になる。例へばこんな風に。
foo' :: (a -> [a]) -> [Int]
foo' f = [123] -- f を呼ばないから問題無い

 以上が現在の私の理解に於ける rank-2 polymorphism(ランク2多相性)である。forall の使ひ方には他にも extentially quantified type(存在量化された型)や rank-N polymorphism(ランクN多相性)がある。前者は下にある WikiBooks の記事を讀めば簡單に分かるが、問題は後者だ。ランク2多相性を拡張した概念のやうだが、まだ私は理解してゐない。

で、これを何に使ふのか?

 GHC のソースを grep してみたら、GHC の内部の libraries/base/GHC/Base.lhs で使はれてゐた。どうもコンパイルの過程で使はれるやうな感じだ。…つまり、どう使へば良いのか良く分かりません。

資料

Haskell/Extentially quantified types
7.4.8. Arbitrary-rank polymorphism

2002
   10 11 12
2003
   1 2 3 4 5 6 7 8 9 10 11 12
2004
   1 2 3 4 5 6 7 8 9 10 11 12
2005
   1 2 3 4 5 6 7 8 9 10 11 12
2006
   1 2 3 4 6 7 8 9 10 11 12
2007
   1 2 3 4 5 6 7 8 9 10 12
2008
   1 4

login