仕組みがわかりにくかった。
2025年8月21日木曜日
Haskell入門 P347 ユーザー登録のためのINSERT
2025年8月18日月曜日
Haskell入門 P326 処理のまとめ
Haskell入門 P323 テストようやく終了
本のままでは、動かず新しいバージョンに合わせた修正が必要だった。
左辺の(JqQueryObject o) vは{"name":.name,"age":.age}::[(Text,JqQuery)]右辺の fmap $ flip executeQuery v のflipは引数を逆順にして、部分適用を意図した 通りにするために使う。(flip executeQuery v) q == executeQuery q vfmap (fmap $ flip executeQuery v) は、内側のfmapで( , )への処理を、外側のfmapで上の関数使って[ , , ]への処理を行う。sequenceは①で Eitherを外に出していく [(either Text (Text,Value))]②で Ehter Text [(Text,Value)]にする
パーシングは、なかなか複雑
2025年8月16日土曜日
Haskell入門 P318
スペースがある場合のパース
Spec.hs
2. lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc
目的:トークンを読んだあと、自動で空白をスキップする
使い方:
lexeme L.decimal -- 数字を読み取ったあと、空白を消費
lexeme (some letterChar) -- 識別子を読み取ったあと、空白を消費
イメージ:
入力: "123 "
lexeme L.decimal → 123 を返す、空白も消費ない場合は、後ろの空白が残り、パースが失敗しやすくなります。
3. symbol :: String -> Parser String
symbol = L.symbol sc
目的:記号(キーワードや演算子)を読んだあと空白をスキップ
例:
symbol "." -- ドットを読み取り、空白も消費 symbol "[" -- 左ブラケットを読み取り、空白も消費 内部的には lexeme (string s) と同じような働きです。
4. schar :: Char -> Parser Char
schar c = lexeme (char c)
目的:単一文字のトークンを読み取り、空白をスキップ
文字 . や [ ] の後ろに空白があっても問題なくパースできる
例:
schar '.' -- "." と後ろの空白をまとめて消費 schar '[' -- "[" と後ろの空白をまとめて消費
Haskell入門 P316 修正コード
P316のコードが動作しなかったので、ChatGPTから同等のものに書き直してもらったのがこちら。新しいライブラリMegaparsecを使うといいらしい。
Parser.hs
Parser a = Parsec Void String a
限られた使い方 aが結果 Parsecのほうがカスタマイズしやすいといえる
・try paraseIndex <|> try parseField <|> pure JqNil で<|>は左が失敗したら右ためす
tryは 失敗しても入力を消費せず次を代わりにためす (入力を巻き戻す)
・some letterChar : some 1回以上繰り返し letterChar a~zA~Zのパース
・option JqNil (char '.' *> filterRest <|> parseField)
option:: a -> Parser a -> Parser a
ディフォルト値->試すパーサ->失敗したら ディフォルトaを返す
char '.' *> filterRest : .を消費し、filterRest返す
ここではtry不要。すでにfilterRestの中でtryは終えているので
Haskell入門 P316
結局、コードが古くてうまく動作せず、別のライブラリを使うことになった。
でも、いちおう、古いほうも、コードをいろいろ確認してみた。
・showParserResult $ parse (jqFilterParser <* endOfInput) s `feed` ""は
showParserResult $ (parse (jqFilterParser <* endOfInput) s) `feed` ""と同じ意味
<* endOfInput 該当しないところはパースせず `feed` ""はパース停止の決まり文句のようなものらしい
・fmap pack $ many1 (letter <|> char '-' <|>..... digit())について
many1 は letter <|> char '-' <|> ... <|> digit は 1文字分のパーサー
many1 (...) はこれを 1回以上繰り返して成功した結果をリスト [Char] にまとめる
fmap pack
によって [Char]
→ Text
に変換 letter :: Parser Char なので many1 letter :: Parser [Char] になります。
箱(Parser)はそのままで 中身 [Char] が Text に変わる
・JqIndex <$> パース1 <*> バース2 の意味について復習
<$>で最初に部分適用の関数ができて、その関数のまだ未適用な部分に<*>を順次適用していくしくみ
パーサの場合、関数がつぎつぎと、無限に適用できる引数があるようなもの。その場合は、つねに、部分適用な関数のままでJqIndexが残ることになるといえそう。再帰状態になるのかも。
2025年8月13日水曜日
Haskell入門 P315 パーサの作成
本のコードのままではだめで、けっこう厳密さが要求された。バージョンの違いか?
・Text と String は別物 (T.pack ".")で Textに
・コンストラクタもエクスポートリストで見えるようにする (..)など利用
・stack.yaml / package.yaml の依存関係はビルド対象ごとに確認(ライブラリも指定)
Parser.hs
Hjq.hs
package.yaml