tsurushuuの日記

2011-09-28

GetOpt

00:07

普段は、Haskellの事についても、普通の日記にだらだらと書いていましたが、どうせなのでグループの日記として書いてみます。

引数を受け取る型

00:07

GetOptで引数を受け取るための「型」が、手続き型に慣れていると、なんとなく不思議な気持ちになるのだったが、以下のページのTowards a higher level の章が良く説明されていた。

これは、ドキュメントのサンプルの二つ目に近い。


オブションの定義の際に出てくる、String->a は、「引数のStringを受け取って、a を返す」と解釈できる。

ここで、簡単な例だが、 a が単なる値だとすると、多少まどろっこしい事態が起こる。

./main -i"test" -o"hoge" -i"fuga"

このような実行をすると、引数の解析結果として、[Input "test", Out "hoge", Input "fuga"] のようなリストが返ってくる。ここで、Input の内容を、適当に限定する事は簡単だけども、そのような細かい事を考慮していたのでは、「GetOptで引数の解析をした後も、引数の解析から逃れる事が出来ない」という、なんとも不甲斐ない事実に気づく。

この事を考えると、ドキュメントの二つ目の例の、引数を Options -> Options という関数でうける方法は、書き方は多少長ったらしいが、非常にスマートに見えてきた。

コード

00:43

GetOpt結果をIntなどに変換にするようなサンプルが見当たらないのが気になる。パースの際に、Intへの変換まで行ってしまうと、エラーの状況が増えるからだろうか。

data Options = Options {
      queryArg :: String,
      rppArg :: Int,
      langArg :: String
    } deriving Show

defaultOptions = Options {
                   queryArg = "",
                   rppArg = 100,
                   langArg = "ja"
                 }

options :: [OptDescr (Options -> Options)]
options = [
 Option ['q'] ["query"] (ReqArg (\str os -> os  { queryArg = str } ) "STRING") "query string",
 Option ['r'] ["rpp"] (ReqArg (\str os -> os  { rppArg = read str } ) "INT") "rpp",
 Option ['l'] ["lang"] (ReqArg (\str os -> os  { langArg = str } ) "LANG") "language \"ja\""
 ]

main :: IO ()
main = do
  args <- getArgs
  (os, n) <- case getOpt Permute options args of
         (o, n, []) -> return (foldl (flip id) defaultOptions o, n )
  let
      rpp = rppArg os
      strRaw = queryArg os
      es = encodeString strRaw
      lang = langArg os
  print os
  print n

それと、オプションの定義の際の、最後のStringは、どんな文字列を入れればいいんだろうか。。実際にはドキュメントとして表示するだけだと思われるが、なにか慣習でもあるのだろうか・・・

ReqArg (String -> a) String

時刻

01:54

今現在の時刻を取得

module Main where

import Data.Time (getZonedTime, formatTime)
import System.Locale (defaultTimeLocale)

main = do
  now <- getZonedTime
  print now
  print $ formatTime defaultTimeLocale "%Y%m%d_%H:%M:%S" now