top page > computer > haskell > web_lecture > for_programmer > nml5.html
更新日:
文責: 重城良国

NML(Nano Markup Language): 5. スタンドアロンなデコーダ、エンコーダ

Books.hs

変換する

本のリストのHaskellデータ型による表現とNMLによる表現とを相互に変換するプログラムを作成する。入出力は標準入出力を使う。

Haskellデータ型の読みこみ

Haskellのデータ型を文字列から読みこめるようにする。derivingにReadを追加する。

data Book = Book {
title :: String,
author :: String }
deriving (Show, Read)

サンプルファイル

以下のサンプルファイルを作成(またはコピペ、ダウンロード)しておこう。

booklist.nml

<books>

<book>
<title>The Old Man and the Sea</title>
<author>Ernest Hemingway</author>
</book>

<book>
<title>The Catcher in the Rye</title>
<author>J. D. Salinger</author>
</book>

</books>

booklist.dat

[
Book {title = "The Old Man and the Sea", author = "Ernest Hemingway"},
Book {title = "The Catcher in the Rye", author = "J. D. Salinger"}
]

NMLからHaskellのデータ型への変換

decodeBooks.hs

import Books

main :: IO ()
main = interact $ maybe "" ((++ "\n") . show) . booklist

% cat booklist.nml | runghc decodeBooks.hs
[Book {title = "The Old Man and the Sea", author = "Ernest Hemingway"},Book {title = "The Catcher in the Rye", author = "J. D. Salinger"}]

Haskellのデータ型からNMLへの変換

encodeBooks.hs

import Books

main :: IO ()
main = interact $ fromBooklist . read

% cat booklist.dat | runghc encodeBooks.hs
<books><book><title>The Old Man and the Sea</title><author>Ernest Hemingway</author></book><book><title>The Catcher in the Rye</title><author>J. D. Salinger</author></book></books>

整形

Nml.hs

encodeBooksは1行にだらだらと出力する。改行やインデントによるある程度の整形がしたい。モジュールNmlの関数fromNmlとtoStringを修正する。

fromNml :: Nml -> String
fromNml = toString 0 . toTokens

関数idtはインデントする。関数opn, clsはそれぞれ開きタグ、閉じタグを作る。

idt :: Int -> String -> String
idt i = (replicate i '\t' ++)

opn, cls :: String -> String
opn = ('<' :) . (++ ">")
cls = ("</" ++) . (++ ">")

toString :: Int -> [Token] -> String
toString i (Open tg : Text tx : Close tg' : ts) =
idt i $ open tg ++ tx ++ cls tg' ++ "\n" ++ toString i ts
toString i (Open tg : ts) = idt i $ opn tg ++ "\n" ++ toString (i + 1) ts
toString i (Close tg : ts) = idt (i - 1) $ cls tg ++ "\n" ++ toString (i - 1) ts
toString i (Text tx : ts) = idt i $ tx ++ "\n" ++ toString i ts
toString _ _ = ""

「現在のインデント数」を変数iとして次々と渡していく。開きタグと閉じタグのあいだに単一の文字列のみのときにはそれらを1行にまとめインデントはそのままにする。開きタグの場合はその後のインデントを深くし、閉じタグならばその後のインデントを浅くする。テキストならばインデントはそのままにする。

% cat booklist.dat | runghc encodeBooks.hs
<books>
<book>
<title>The Old Man and the Sea</title>
<author>Ernest Hemingway</author>
</book>
<book>
<title>The Catcher in the Rye</title>
<author>J. D. Salinger</author>
</book>
</books>

まとめ

標準入力から読みこみ、標準出力へ書きだす形でNml形式とHaskellのデータ型とのあいだでの相互変換関数を作成した。

「機能: main」へもどる 「ボットを作る: はじめに」へ

正当なCSSです! HTML5 Powered with CSS3 / styling, and Semantics