文字列のフォーマット

224 views
Skip to first unread message

syuju

unread,
May 3, 2013, 11:39:03 AM5/3/13
to haske...@googlegroups.com
皆さん、こんばんは。(^^
syujuです。
 
早速ですが、件名にあるとおり、文字列のフォーマットで悩んでいます。
c言語ではprintf関数などが用意されていると思いますが、Haskellでの定番は存在するのでしょうか。
 
タプルで与えられる年月日データ(Int,Int,Int)をyyyy/mm/dd のように整形する為に使用したいと思っています。
(1月の場合は 01のように0でパッドします)
 
軽く探してみたのですが、このような用途にふさわしい関数を発見できなかったので、もし便利な関数があるようでしたら教えてください。m( _ _ )m
 
ちなみに、現在は以下のように関数を定義して使用しています。我ながら酷い感じになのですが。
(西暦は必ず4桁なのでshowを使うだけでよいのですが、あえて関数を使って統一感をだしてみました。関数名は適当です)
 

formatDate :: (Int,Int,Int) -> String
formatDate (y,m,d) = prettyInt y 4 '0' ++ "/"
                  ++ prettyInt m 2 '0' ++ "/"
                  ++ prettyInt d 2 '0'

prettyInt :: Int -> Int -> Char -> String
prettyInt val width padChar | length str >= width = str
                            | otherwise = [ padChar | i <-[1..(width - (length str))] ]] ++ str
  where
    str = show val
 
 
++や生成器を多用しているので、たぶん非効率だと思いますが、代替手段が思い浮かばない次第です・・・。
もし宜しければ、このコードに関してもアドバイス頂けると嬉しいです。
 
では。
 

齊藤

unread,
May 3, 2013, 12:40:42 PM5/3/13
to haske...@googlegroups.com

> 早速ですが、件名にあるとおり、文字列のフォーマットで悩んでいます。
> c言語ではprintf関数などが用意されていると思いますが、
> Haskellでの定番は存在するのでしょうか。

Text.Printf モジュールの printf 関数などどうでしょうか。
ほぼ printf のような感覚で使えるので楽だと思います。
Haskell 的にはちょっと邪道ですが…。
----
齊藤

philopon

unread,
May 4, 2013, 11:34:08 AM5/4/13
to haske...@googlegroups.com
こんばんは、syujuさん。

日付のデータを使用するのであれば、timeパッケージのData.Time.Calendar.Dayを使用されてはいかがでしょうか。

不要かとは思いますが、以下に対応する関数を書きました。formatTimeのフォーマット指定についてはhaddockをご覧ください。

import Data.Time
import System.Locale

fromDate :: (Integer, Int, Int) -> Day
fromDate (y, m, d) = fromGregorian y m d

formatDate :: Day -> String
formatDate = formatTime defaultTimeLocale "%Y/%m/%d"

お力になれれば幸いです。

syuju

unread,
May 4, 2013, 9:35:40 PM5/4/13
to haske...@googlegroups.com
齊藤さん
 
返信ありがとうございます。
syujuです。
 
Text.Printf モジュールのご紹介、ありがとうございます。
今後文字列の整形が必要な場合は使ってみたいと思います。
ちなみに、Haskell 的に邪道とのことですが、正道はどんな感じになるのでしょうか・・・。
すみません、周りにHaskellを使っている人がいないので、一般的な方法がまったく分からない次第です。
m (_ _) m
 

syuju

unread,
May 4, 2013, 9:55:21 PM5/4/13
to haske...@googlegroups.com
philopon さん
 
返信ありがとうございます。
syujuです。
 
timeパッケージのご紹介ありがとうございます。
大変参考になりました。
 
今作成しているアプリとは無関係ですが、このパッケージを使って作ってみたいものが一つ思い浮かびました。
 
書いて頂いた関数はパクらせて頂きます。 m (_ _) m
 

齊藤

unread,
May 6, 2013, 11:14:21 AM5/6/13
to haske...@googlegroups.com

printf が邪道だと述べたのは、データと書式指定との間に矛盾があってもコン
パイル時にエラーとして検出できないからです。例えばこんなコードをコンパ
イルしてみて下さい。

import Text.Printf
main = printf "%d\n" (23::Int) "123"

コンパイル時にはエラーにならず、実行時にエラーが報告されます。 折角
Haskell を使っているのですから、こういったしょうもないミスはコンパイル
時に検出して欲しいものです。

C++ で言うところの iostream 的なものがあればいいんですが、検索してもそ
れらしいものが見当りませんね。 あるいは Template Haskell の機能を使えば
必要数のデータを受けとる関数を書式指定から生成することも出来そうな気が
します。

私もまだ Haskell の経験は浅いので他の人の意見を知りたいところです。
----
齊藤

syuju

unread,
May 7, 2013, 9:52:47 PM5/7/13
to haske...@googlegroups.com
齊藤さん

返信ありがとうございます。
syujuです。
 
理解いたしました。
確かに事前に型チェックできる方がHaskellらしいですね。
 
今更ですが、そういう意味ではprintf関数は上手くまとめてありますね・・・。
 
Haskellでプログラムを書き始めて半年以上経ちましたが、自分の進歩の無さが寒々しく思えます。(^^;
 

2013年5月7日火曜日 0時14分21秒 UTC+9 齊藤:

nobu_t...@nifty.com

unread,
May 7, 2013, 10:49:27 PM5/7/13
to haske...@googlegroups.com
豊福です。

>> prettyInt :: Int -> Int -> Char -> String
>> prettyInt val width padChar | length str >= width = str
>> | otherwise = [ padChar | i <-[1..(width - (len
gth str))] ]] ++ str
>> where
>> str = show val

短く書くんだったら(replicate に負数を渡しても大丈夫みたいなので)

prettyInt val width padChar = replicate (width - length str) padChar ++ str
where str = show val

ですか。
---

Katsutoshi Itoh

unread,
May 13, 2013, 9:59:43 PM5/13/13
to haske...@googlegroups.com
Fun of ProgramingのPhantom Typeの章には型安全なprint formatのコードが出てますね.
これが個人的には解じゃないかと思います.


2013年5月7日 0:14 齊藤 <mald...@gmail.com>:

--
このメールは Google グループのグループ「haskell-jp」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、haskell-jp+...@googlegroups.com にメールを送信します。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。





--
----
いとう かつとし
cuts...@gmail.com

syuju

unread,
May 15, 2013, 6:38:29 AM5/15/13
to haske...@googlegroups.com
豊福さん。

ご回答ありがとうございます。
すっきり書けていい感じです。

ありがとうございました。 m (_ _) m

replicate関数を自力で見つける為にもHoogleをもう少し上手く使いこなしたいです・・・。

syuju

2013年5月8日水曜日 11時49分27秒 UTC+9 hyappen itto:

syuju

unread,
May 15, 2013, 6:42:10 AM5/15/13
to haske...@googlegroups.com
難しそうな本ですね・・・。(^^;

2013年5月14日火曜日 10時59分43秒 UTC+9 cutsea110:
Fun of ProgramingのPhantom Typeの章には型安全なprint formatのコードが出てますね.
これが個人的には解じゃないかと思います.
2013年5月7日 0:14 齊藤 <mald...@gmail.com>:

printf が邪道だと述べたのは、データと書式指定との間に矛盾があってもコン
パイル時にエラーとして検出できないからです。例えばこんなコードをコンパ
イルしてみて下さい。

import Text.Printf
main = printf "%d\n" (23::Int) "123"

コンパイル時にはエラーにならず、実行時にエラーが報告されます。 折角
Haskell を使っているのですから、こういったしょうもないミスはコンパイル
時に検出して欲しいものです。

C++ で言うところの iostream 的なものがあればいいんですが、検索してもそ
れらしいものが見当りませんね。 あるいは Template Haskell の機能を使えば
必要数のデータを受けとる関数を書式指定から生成することも出来そうな気が
します。

私もまだ Haskell の経験は浅いので他の人の意見を知りたいところです。
----
齊藤

--
このメールは Google グループのグループ「haskell-jp」の登録者に送られています。
このグループから退会し、メールの受信を停止するには、haskell-jp+unsubscribe@googlegroups.com にメールを送信します。
その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。


Reply all
Reply to author
Forward
0 new messages