前へ 目次 次へ
参照: cabal-instsll 関連のリンク Distribution.Simple.Commnad Distribution.Simple.Setup 今回からは、Distribution.Simple.Command で定義されている代数的データ型をひとつひとつ眺めていく。 最初は CommnadUI 型だ。CommnadUI 型には Hddock 文書によれば、Cabal の様々なサブコマンドの名前、説明、フラグのセットがまとめられている。CommnadUI のコンストラクタは CommnadUI 1つだが、次のようなフィールド名のパラメータを持っている。 CommnadUI commandName :: String commandSynopsis :: String commandUsage :: String -> String commandDescription :: Maybe (String -> String) commandDefaultFlags :: flags commandOptions :: ShowParseArgs -> [OptionField flags] 各フィールドの意味は以前の記事で調べたので、ここでは CommandUI 型のデータから各フィールドの値を取り出す方法を考えてみる。幸い Distribution.Simple.Setup には globalCommand という CommnadUI 型のデータが定義されているので、それを材料に ghci でテストしてみる事ができる。 まずは、Distribution.Simple.Command と Distribution.Simple.Setup と Data.Maybe をインポートする。 Prelude> import Distribution.Simple.Command Prelude Distribution.Simple.Command> import Distribution.Simple.Setup Prelude Distribution.Simple.Command Distribution.Simple.Setup> import Data.Maybe Prelude Distribution.Simple.Command Distribution.Simple.Setup Data.Maybe> :set prompt "ghci> " ghci> commandName と commandSynopsis はフィールド名と同じアクセサで簡単に取り出せる。 ghci> commandName globalCommand "" ghci> commandSynopsis globalCommand "" commandUsage フィールドのデータは String -> String 型の関数だから、文字列の引数が必要だ。 ghci> (commandUsage globalCommand) "cabal" "This Setup program uses the Haskell Cabal Infrastructure.\nSee http://www.haskell.org/cabal/ for more information.\n" これには putStr を使った方がいいかもしれない。 ghci> putStr $ (commandUsage globalCommand) "cabal" This Setup program uses the Haskell Cabal Infrastructure. See http://www.haskell.org/cabal/ for more information. commandDescription フィールドのデータは Maybe (String -> String) 型を取り出すためには、Maybe 型のコンテナからデータを取り出さなければならない。今回は Data.Maybe モジュールの fromJust 関数を使う。 ghci> putStr $ (fromJust $ commandDescription globalCommand) "cabal" For more information about a command use cabal COMMAND --help Typical steps for installing Cabal packages: cabal configure cabal build cabal install commandDefaultFlags フィールドのデータは flags という型変数になっている。Distribution.Simple.Setup モジュールのフラグ型が分からないので :t コマンドで調べてみる。 ghci> :t commandDefaultFlags globalCommand commandDefaultFlags globalCommand :: GlobalFlags GlobalFlags は Distribution.Simple.Setup で次のように定義されている。 data GlobalFlags = GlobalFlags { globalVersion :: Flag Bool, globalNumericVersion :: Flag Bool } GlobalFlags のフィールドにもアクセスしてみる。 ghci> globalVersion $ commandDefaultFlags globalCommand Flag False Flag 型も Distribution.Simple.Setup.hs で定義されている。 data Flag a = Flag a | NoFlag deriving (Show, Read, Eq) commandDefaultFlags のフラグのセットは、commandsRun がコマンド・ラインオプションを解析してフラグを設定するときのデフォールトの値になる。globalCommand の commandDefaultFlags の値は、 {globalVersion = Flag False, globalNumericVersion = Flag False} だ。 commandOptions フィールドの値は複雑で Show クラスのインスタンスでもないので、ghci のコマンド・ラインでは表示できない。このような場合は :t コマンドでデータ型を表示させるとよい。 ghci> :t commandOptions globalCommand commandOptions globalCommand :: ShowOrParseArgs -> [OptionField GlobalFlags] ShowOrParseArgs は Distribution.Simple.Command モジュールで定義されている。 data ShowOrParseArgs = ShowArgs | ParseArgs ghci> :t commandOptions globalCommand ShowArgs commandOptions globalCommand ShowArgs :: [OptionField GlobalFlags] OptionField 型は2つのフィールドを持っている。 OptionField optionName :: Name optionDescr :: [Descr a] optionName の方を試してみる。Name は単なる String の別名なので ghci で表示できる。 ghci> optionName $ head $ commandOptions globalCommand ShowArgs "version" commandOptions フィールドのリストの optionName を全て取り出してみた。 ghci> map optionName $ commandOptions globalCommand ShowArgs ["version","numeric-version"] "version" オプションの optionDescr フィールドの値を取り出してみた。 ghci> :t optionDescr $ head $ commandOptions globalCommand ShowArgs optionDescr $ head $ commandOptions globalCommand ShowArgs :: [OptDescr GlobalFlags] [OptDessr GlobalFlags] の最初の要素を取り出し foo に束縛した。 ghci> let foo = head $ optionDescr $ head $ commandOptions globalCommand ShowArgs ghci> :t foo foo :: OptDescr GlobalFlags OptDescr a 型の定義も Distribution.Simple.Command にあるが、コンストラクタが4つあり、フィールドの構成も複雑だ。 OptDescr a ReqArg Description OptFlags ArgPlaceHolder (ReadE (a -> a)) (a -> [String]) OptArg Description OptFlags ArgPlaceHolder (ReadE (a -> a)) (a -> a) (a -> [Maybe String]) ChoiceOpt [(Description, OptFlags, a -> a, a -> Bool)] BoolOpt Description OptFlags OptFlags (Bool -> a -> a) (a -> Maybe Bool) foo のコンストラクタがどれに一致するのかわからず試行錯誤したが、ChoiceOpt のようだ。 ghci> let ChoiceOpt a = foo ghci> a a の型を調べてみた。 ghci> :t a a :: [(Description, OptFlags, GlobalFlags -> GlobalFlags, GlobalFlags -> Bool)] a の先頭の要素を取り出した。 ghci> :t head a head a :: (Description, OptFlags, GlobalFlags -> GlobalFlags, GlobalFlags -> Bool) head a のパラメータをパターンマッチで取り出してそれぞれの内容を確認した。 ghci> let (w,x,y,z) = head a ghci> w "Print version information" ghci> x ("V",["version"]) ghci> :t y y :: GlobalFlags -> GlobalFlags ghci> :t z z :: GlobalFlags -> Bool こうしてみると、CommandUI 抽象が非常に複雑な情報を1つの値として保持していることがわかる。また、ここでやった値の取り出し方は、プログラムで行う方法と同じなので、プログラムを読むのが楽になるだろう。 とりだしたパラメータの y は GlobalFlags -> GlobalFlags の形の関数なのでフラグセットの操作をするのではないかと思われる。それでデフォールトのフラグセット commandDefaultFlags に関数適用したらどうなるかが気になってきた。 まずデフォールトのフラグセットを取り出して bar にバインドした。 ghci> let bar = commandDefaultFlags globalCommand 次にフラグセットの内容をリスト表示に変換する関数 flagsToList を定義した。 ghci> let flagsToList flag = [globalVersion flag, globalNumericVersion flag] flagsToList を使って bar の内容を見ると次のようになる。 ghci> flagsToList bar [Flag False,Flag False] bar に y を適用してみた。 ghci> flagsToList $ y bar [Flag True,Flag False] globalVersion のフラグが立っている。 z :: GlobalFlags -> Bool も試してみた。 ghci> z bar False ghci> z $ y bar True どうやら z は GlobalFlags の globalVersion フラグが立っているかどうかを判定しているようだ。 CommandUI の内容を手動で操作できると、それぞれのパラメータの意味が体感的に理解できるので、プログラムのイメージが作りやすい。
by tnomura9
| 2014-01-06 23:41
| Haskell
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||