メッセージ。 - diary
2009-07-24
# Haskellでの正規表現
Haskellでの正規表現の扱い(とくに日本語を扱う方法について)を書きました→memo - Haskell。
2009-07-15
# Haskellでの日本語の扱い
Haskellでの日本語の扱いについて書きました。→memo - Haskell
あまりまとまっていないけど、ネット上であまり情報が見つけられなかったので、こんなのでも何かの役に立てば。Schemeもそうだけど、Haskellもあまり情報がないんだよなー。みんな賢いから自分で解決しちゃうのかもしれない。あと、ぼくがやりたいことって、普通のSchemerやHaskellerからするとレベルが低い(俗っぽい)ので、そういう情報にみんなあまり興味がないのかもしれない。ということで、逆にぼくからするとこの関連は書きやすい。
あまりまとまっていないけど、ネット上であまり情報が見つけられなかったので、こんなのでも何かの役に立てば。Schemeもそうだけど、Haskellもあまり情報がないんだよなー。みんな賢いから自分で解決しちゃうのかもしれない。あと、ぼくがやりたいことって、普通のSchemerやHaskellerからするとレベルが低い(俗っぽい)ので、そういう情報にみんなあまり興味がないのかもしれない。ということで、逆にぼくからするとこの関連は書きやすい。
2009-07-13
# Haskellでよくやるミス
つまらないミスで躓き、何時間もロスして嫌になった。よくやるミス(バグの元)なのでメモしておく。
このコードを動かすと、(たぶん遅延評価とのコンボによって)プログラムが固まってしまい実行が前に進まなくなった。なぜかというと、要するに変数名がバッティングしているのだ。mapの中で「\l->」として変数lを使用しようとしているのだが、一方で「let (u:l:ss) = 」としてLet式の中でも値を変数lに束縛しようとしている。
このようなコードは、Schemeでは問題なく動く。より内側にある変数束縛(この場合はLet式)が、外側の変数束縛(\l->)より優先(隠蔽)するので、「\l->」をまったく気にしなくてよくなるのだ。変数名を考えるのが面倒なので、ぼくはこういうことをよくやる。ところがHaskellでは、このようなケースで変数lがバッティングしてしまうのだ。その結果、プログラムがまったく想定していない挙動をすることになる。
とくにHaskellでは、型宣言を併用することで極端に短い変数名を使うことが多い。変数名が短くても、それがなにを意味するのか、型を見ることで判別できるからだ。しかし、変数名が短くなったことによって、変数名がバッティングしやすくもなった。そして変数名がバッティングしたときのペナルティは非常に大きい。またGHCコンパイラも警告してくれない。
なので、この件についてはよくよく注意してプログラムを組まなくてはならない。>自分
map (\l-> let (u:l:ss) = stringSplit "\t" l in (u,map read ss)) $ lines cs
Haskellでよくやるミス
このコードを動かすと、(たぶん遅延評価とのコンボによって)プログラムが固まってしまい実行が前に進まなくなった。なぜかというと、要するに変数名がバッティングしているのだ。mapの中で「\l->」として変数lを使用しようとしているのだが、一方で「let (u:l:ss) = 」としてLet式の中でも値を変数lに束縛しようとしている。
このようなコードは、Schemeでは問題なく動く。より内側にある変数束縛(この場合はLet式)が、外側の変数束縛(\l->)より優先(隠蔽)するので、「\l->」をまったく気にしなくてよくなるのだ。変数名を考えるのが面倒なので、ぼくはこういうことをよくやる。ところがHaskellでは、このようなケースで変数lがバッティングしてしまうのだ。その結果、プログラムがまったく想定していない挙動をすることになる。
とくにHaskellでは、型宣言を併用することで極端に短い変数名を使うことが多い。変数名が短くても、それがなにを意味するのか、型を見ることで判別できるからだ。しかし、変数名が短くなったことによって、変数名がバッティングしやすくもなった。そして変数名がバッティングしたときのペナルティは非常に大きい。またGHCコンパイラも警告してくれない。
なので、この件についてはよくよく注意してプログラムを組まなくてはならない。>自分
# Haskellでの日付・時刻の処理
Haskellの習作として、RSSのパーサーを作ってみた。その際、日付・時刻情報の取り扱い、とくにRSS中の時刻情報(文字列)をパースして内部表現に変換する方法を模索した。Webを検索もしてみたのだが、そういった情報はあまり見つからなかったので、ここにメモをしておく(この模索では、処理系としてGHCを使用したため、ここに書いた情報ではほかの処理系に適合しない場合もあるかと思います)。
『Real World Haskell』の20章を見たところ、Haskellでは基本的にClockTimeというデータ型を使うのが便利らしい。GHCのマニュアルでいうとSystem.Timeの項に説明がある。Eq、Ord、Showクラスのインスタンスなので、日付どうしを比較したり、デバッグ用にshowで文字列変換したりするのも簡単だ。ClockTimeは、内部的に1970年1月1日からの秒数を持っていて、UNIXでの標準的な時刻の扱いに近い。
ところが一方で、ClockTime型の値を任意フォーマットの文字列に変換したり、逆に時刻情報を記述した文字列を読み込んでClockTime型に変換したりする方法は、標準では用意されていないようだ。GHCマニュアルの中では見つけられなかった。そこで、そういった機能は拡張パッケージで提供されているのかもしれないと、パッケージを探してみた。
ぼくは、GHCの開発環境としてDebian lennyを使っているので、apt-cache search ghcとしてみる。すると、次のパッケージが怪しそうだ。インストールしてGHCのマニュアル(file:///usr/share/doc/ghc6-doc/index.html)を再読み込みしてみる。
「Data.Time.Format」というモジュールができていることに気付いた。parseTimeやformatTimeのように、文字列と内部表現の橋渡しをしてくれそうな関数も見える。
ParseTime tというのがよく分からなかったのだけど、どうやら次の内部表現に対応しているということらしい。とくに、UTCTimeというのはClockTimeと同じようなもので、年月日+時刻を扱うのに良さそう。
今回はRSS 2.0から日付・時刻情報をパースするので、次のようにすれば良い。
内部表現を文字列に変換する場合は、次のようになる。
と、うまくいけば格好良いのだけど、厳密にはこの実行結果は正しくない(W3Cの日付フォーマットに従っていない)。正しくは「"2009-06-29T14:11:08+00:00"」と、最後のタイムゾーンにコロンが入っているのだ。ここをうまく解決する方法は、まだ見つけていない。
あと、RFC822の文字列をパースするとき、西暦が「2009」のような4桁ならばうまく動くのだけど、ここが2桁だった場合も期待したように動かない。この場合、コードと実行結果は次のようになる。
1909年と解釈してしまうのだ。これも、ちょっと解決策は見つかっていない。ということで、parseTimeとformatTimeを使う方法も、ちょっと足りないようだ…。まぁ、この程度なら大きな問題ではないので、独自実装するほうがよいのかもしれない。いつも思うことながら、日付の問題は案外面倒くさいですね。
『Real World Haskell』の20章を見たところ、Haskellでは基本的にClockTimeというデータ型を使うのが便利らしい。GHCのマニュアルでいうとSystem.Timeの項に説明がある。Eq、Ord、Showクラスのインスタンスなので、日付どうしを比較したり、デバッグ用にshowで文字列変換したりするのも簡単だ。ClockTimeは、内部的に1970年1月1日からの秒数を持っていて、UNIXでの標準的な時刻の扱いに近い。
*Main> :m System.Time Prelude System.Time> getClockTime Sun Jul 12 23:38:45 JST 2009
ClockTimeを使ってみる
ところが一方で、ClockTime型の値を任意フォーマットの文字列に変換したり、逆に時刻情報を記述した文字列を読み込んでClockTime型に変換したりする方法は、標準では用意されていないようだ。GHCマニュアルの中では見つけられなかった。そこで、そういった機能は拡張パッケージで提供されているのかもしれないと、パッケージを探してみた。
ぼくは、GHCの開発環境としてDebian lennyを使っているので、apt-cache search ghcとしてみる。すると、次のパッケージが怪しそうだ。インストールしてGHCのマニュアル(file:///usr/share/doc/ghc6-doc/index.html)を再読み込みしてみる。
libghc6-time-dev - Haskell time library for GHC libghc6-time-doc - Haskell time library for GHC; documentation libghc6-time-prof - Haskell time library for GHC; profiling libraries
日付・時刻関連の機能が含まれてそうなパッケージ
「Data.Time.Format」というモジュールができていることに気付いた。parseTimeやformatTimeのように、文字列と内部表現の橋渡しをしてくれそうな関数も見える。
formatTime :: FormatTime t => TimeLocale -> String -> t -> String parseTime :: ParseTime t => TimeLocale -> String -> String -> Maybe t
Data.Time.Formatモジュールに含まれている関数(抜粋)
ParseTime tというのがよく分からなかったのだけど、どうやら次の内部表現に対応しているということらしい。とくに、UTCTimeというのはClockTimeと同じようなもので、年月日+時刻を扱うのに良さそう。
ParseTime Day ParseTime LocalTime ParseTime TimeOfDay ParseTime TimeZone ParseTime UTCTime ParseTime ZonedTime
Data.Time.Formatモジュールで扱う日付・時刻の内部表現
今回はRSS 2.0から日付・時刻情報をパースするので、次のようにすれば良い。
import Data.Time import Data.Time.Format import System.Locale import Maybe parseRFC822 :: String -> UTCTime parseRFC822 s = fromJust $ parseTime defaultTimeLocale "%a, %d %b %Y %T %z" s main = print $ parseRFC822 "Mon, 29 Jun 2009 14:11:08 +0000" -- 実行結果 2009-06-29 14:11:08 UTC
RSS 2.0のpubDate要素から日付・時刻情報を内部表現に変換する
内部表現を文字列に変換する場合は、次のようになる。
import Data.Time import Data.Time.Format import System.Locale import Maybe parseRFC822 :: String -> UTCTime parseRFC822 s = fromJust $ parseTime defaultTimeLocale "%a, %d %b %Y %T %z" s showW3CDate :: UTCTime -> String showW3CDate = formatTime defaultTimeLocale "%Y-%m-%dT%T%z" main = do t <- return $ parseRFC822 "Mon, 29 Jun 2009 14:11:08 +0000" print $ showW3CDate t -- 実行結果 "2009-06-29T14:11:08+0000"
内部表現のUTCTimeを文字列に変換する場合
と、うまくいけば格好良いのだけど、厳密にはこの実行結果は正しくない(W3Cの日付フォーマットに従っていない)。正しくは「"2009-06-29T14:11:08+00:00"」と、最後のタイムゾーンにコロンが入っているのだ。ここをうまく解決する方法は、まだ見つけていない。
あと、RFC822の文字列をパースするとき、西暦が「2009」のような4桁ならばうまく動くのだけど、ここが2桁だった場合も期待したように動かない。この場合、コードと実行結果は次のようになる。
parseRFC822 :: String -> UTCTime parseRFC822 s = fromJust $ parseTime defaultTimeLocale "%a, %d %b %y %T %z" s main = print $ parseRFC822 "Mon, 29 Jun 09 14:11:08 +0000" -- 実行結果 1909-06-29 14:11:08 UTC
西暦が2桁の場合のコード(?)
1909年と解釈してしまうのだ。これも、ちょっと解決策は見つかっていない。ということで、parseTimeとformatTimeを使う方法も、ちょっと足りないようだ…。まぁ、この程度なら大きな問題ではないので、独自実装するほうがよいのかもしれない。いつも思うことながら、日付の問題は案外面倒くさいですね。
2009-07-03
# エロゲ規制に関係するかも?メモ
このへんを読んでいて、ちょっと思ったのでメモ。
「エロゲみたいな異常な趣味は禁止しろ」というような思想は、公園の問題に似ているのかも。
大人たち(の一部)は、子供に対して公園で遊ぶことを望んだりする。公園にある遊具は、遊ぶために作られた道具で、それを正しく使って遊べば、安全で綺麗なのかもしれない。
でも子供にとっては公園で遊ぶことは案外つまらなかったりする。遊具を決められたとおりに正しく使って正しく遊ぶよりも、規格外の遊びを発明して遊ぶほうが楽しいとか。
まぁそもそも、東洋的考えでは、遊びに対して規格みたいなものはあるんだろうか。江戸時代に子供が遊ぶための公園が存在したのかどうか、とか。なんとなくだけど、そういうのはなかったのではないかという気がする。
東洋的考えでは、規格的な遊びとか、規格的人間というのはあまり想定していないのではないかな。一方で、西洋的考えでは「正しい人間」という観念が存在しているのかもしれない、と思う。たとえば渡辺千賀さんが言うような感じで、
人間には魂があって動物には魂がないという考え方は、「人間は動物とは違う」、「人間は神の子だ」という思想のあらわれであるように思う。だとすれば、人間の生き方にたいして「正しい生き方」の存在を想定しているのではないか。
モーゼの十戒のような、「人として、必ず守らなければならない戒律」が、人間の実存のレベルで課せられているというか。
一方で日本人なんかには、「人として、必ず守らなければならない戒律」みたいなものは、存在しないように思う。人間は、どんな悪いことをしようが人間というか。人間という存在を特別視していない。絶対的な善も悪も存在しない。すべては無に帰す。月日は百代の過客にして行き交う人々もまた旅人なりというか。
そういう意味では、男女の別というのもとくに存在しない。正しい性のあり方も存在しない。いや、男女の別は存在はするのだけど。でもそれらは敵ではないというか。ただそれぞれが、それぞれの生をまっとうすればそれでいいんじゃないか、というか。
「エロゲみたいな異常な趣味は禁止しろ」というような思想は、公園の問題に似ているのかも。
大人たち(の一部)は、子供に対して公園で遊ぶことを望んだりする。公園にある遊具は、遊ぶために作られた道具で、それを正しく使って遊べば、安全で綺麗なのかもしれない。
でも子供にとっては公園で遊ぶことは案外つまらなかったりする。遊具を決められたとおりに正しく使って正しく遊ぶよりも、規格外の遊びを発明して遊ぶほうが楽しいとか。
まぁそもそも、東洋的考えでは、遊びに対して規格みたいなものはあるんだろうか。江戸時代に子供が遊ぶための公園が存在したのかどうか、とか。なんとなくだけど、そういうのはなかったのではないかという気がする。
東洋的考えでは、規格的な遊びとか、規格的人間というのはあまり想定していないのではないかな。一方で、西洋的考えでは「正しい人間」という観念が存在しているのかもしれない、と思う。たとえば渡辺千賀さんが言うような感じで、
魂があるから人間はほかの動物よりえらい、みたいな価値観は、アメリカ的には非常に普通なようだが、どうも私の感性には合わない。私に魂があるなら、うちの猫にも魂があると思うし、猫にないなら私にもないと思う。
人間には魂があって動物には魂がないという考え方は、「人間は動物とは違う」、「人間は神の子だ」という思想のあらわれであるように思う。だとすれば、人間の生き方にたいして「正しい生き方」の存在を想定しているのではないか。
モーゼの十戒のような、「人として、必ず守らなければならない戒律」が、人間の実存のレベルで課せられているというか。
一方で日本人なんかには、「人として、必ず守らなければならない戒律」みたいなものは、存在しないように思う。人間は、どんな悪いことをしようが人間というか。人間という存在を特別視していない。絶対的な善も悪も存在しない。すべては無に帰す。月日は百代の過客にして行き交う人々もまた旅人なりというか。
そういう意味では、男女の別というのもとくに存在しない。正しい性のあり方も存在しない。いや、男女の別は存在はするのだけど。でもそれらは敵ではないというか。ただそれぞれが、それぞれの生をまっとうすればそれでいいんじゃないか、というか。
2009-06-21
# 日々
昔テレビで見たんだけど、たしか南米のある民族の人はこんな歌をうたっていた:「神様、わたしたちに死を与えてくれてありがとう」。ぼくはこの歌に大変共感した。
--
iPhoneが欲しい。でも今持っている携帯電話は、まだ使えるんだよね。iPhoneは欲しいけど、まだ使えるものを捨てて、新しいものを買うことに、やはりちょっとは抵抗がある。みんなも実は、そうなんじゃないかな。
でもその一方で、たくさんの人が、日々たくさんのガジェットを買ってもいるようだ。彼らは苦しくないんだろうか。
--
他人を押し退けて自分の居場所を作る若い人がいる。うらやましい。「他人を押し退けて自分の居場所を作れ、若造よ」と言う人がいる。押し潰されそうになる。
面と向かって言えなかったけど、そんなこと、できないよ。したくない。自分の居場所なんて、最小限でいいんだ。最小限がいちばん心地良い。そうじゃないのかな。
今の世の中、他人を押し退ける人がいて問題になっている。でも一方で、今の世の中には、他人を押し退けない人もたくさんいる。世界はぼくらに、「他人を押し退けるな」と言ったその口で、「他人を押し退けろ」と言う。くやしい。
--
背中が煤けてるっていうか。「あんた、背中が煤けてるぜ」と言いたい。でも半面、自分の背中が煤けているような気がする。煤けているのかもしれない。煤けてるんだろう。煤けてる。だからなにも言わない。言えない。
--
iPhoneが欲しい。でも今持っている携帯電話は、まだ使えるんだよね。iPhoneは欲しいけど、まだ使えるものを捨てて、新しいものを買うことに、やはりちょっとは抵抗がある。みんなも実は、そうなんじゃないかな。
でもその一方で、たくさんの人が、日々たくさんのガジェットを買ってもいるようだ。彼らは苦しくないんだろうか。
--
他人を押し退けて自分の居場所を作る若い人がいる。うらやましい。「他人を押し退けて自分の居場所を作れ、若造よ」と言う人がいる。押し潰されそうになる。
面と向かって言えなかったけど、そんなこと、できないよ。したくない。自分の居場所なんて、最小限でいいんだ。最小限がいちばん心地良い。そうじゃないのかな。
今の世の中、他人を押し退ける人がいて問題になっている。でも一方で、今の世の中には、他人を押し退けない人もたくさんいる。世界はぼくらに、「他人を押し退けるな」と言ったその口で、「他人を押し退けろ」と言う。くやしい。
--
背中が煤けてるっていうか。「あんた、背中が煤けてるぜ」と言いたい。でも半面、自分の背中が煤けているような気がする。煤けているのかもしれない。煤けてるんだろう。煤けてる。だからなにも言わない。言えない。