regex-applicative: 内部DSLとしての正規表現

Yuji Yamamoto (山本悠滋)

2019-10-18 Regex Festa

はじめまして! 👋😄

宣伝 hask(_ _)eller

📝今日話すこと

🙊今日話さないこと

regex-applicativeって?

regex-applicativeの例(1)

マッチさせるのに使う関数(他にもある)

match :: RE s a -> [s] -> Maybe a

regex-applicativeの例(1)

ただの文字: sym

> match (sym 'a') "a"
Just 'a' -- 成功したら `Just ...` な値を返す

> match (sym 'a') "b"
Nothing  -- 失敗したら `Nothing` を返す

regex-applicativeの例(2)

連接: *>string

> match (sym 'a' *> sym 'b') "ab"
Just 'b'

-- マッチする文字列は同じ、より分かりやすいバージョン
> match (string "ab") "ab"
Just "ab"

regex-applicativeの例(3)

選択: <|>

> match (sym 'a' <|> sym 'b') "a"
Just 'a'
> match (sym 'a' <|> sym 'b') "b"
Just 'b'

regex-applicativeの例(4)

繰り返し: manysome

> match (many (sym 'a')) "aaaaaaaaaa"
Just "aaaaaaaaaa"

regex-applicativeの例(5)

オプショナルなマッチ: optional

> match (sym 'a' *> optional (sym 'b')) "ab"
Just (Just 'b')
> match (sym 'a' *> optional (sym 'b')) "a"
Just Nothing

regex-applicativeの例(6)

マッチした結果をHaskellの値に割り当て

> match digit "1"
Just 1 -- マッチした結果が整数として返ってくる!
> match (many digit) "12345"
Just [1,2,3,4,5] -- マッチした結果が整数のリストに!

regex-applicativeの例(7)

マッチした結果をHaskellの値に割り当て、さらに計算!

> match (sum <$> many digit) "12345"
Just 15

regex-applicativeの例(7)

もうちょっと複雑な例: まずは部品作り

> schemeRe =
    ((++) <$> string "http" <*> (string "s" <|> pure ""))
      <* string "://"

regex-applicativeの例(7)

もうちょっと複雑な例: まずは部品作り(続き)

> hostRe = some (psym (`elem` ['a'..'z'] ++ "."))
> portRe = sym ':' *> decimal

regex-applicativeの例(7) (続き)

もうちょっと複雑な例: 結合させる

> originRe = schemeRe *> hostRe *> optional portRe

regex-applicativeの例(7) (続き)

もうちょっと複雑な例: 使ってみる

> match originRe "https://example.com:8080"
Just (Just 8080) -- マッチが成功してポート番号がとれた
> match originRe "http://example.com"
Just Nothing     -- マッチは成功したけどポート番号はとれなかった

regex-applicativeの例(8)

マッチ結果の構造体への割り当て: まずは構造体の定義

data Origin =
  Origin { scheme :: String, host :: String, port :: Int }
  deriving Show

regex-applicativeの例(8) (続き)

originRe = Origin   <$>
           schemeRe <*>
           hostRe   <*>
           (portRe <|> pure 80)

regex-applicativeの例(8) (続き)

> match originRe "https://example.com:8080"
Just (Origin {scheme = "https", host = "example.com", port = 8080})
> match originRe "http://example.com"
Just (Origin {scheme = "http", host = "example.com", port = 80})

👍regex-applicativeのメリット

👎regex-applicativeのデメリット

⚙️regex-applicativeの仕組み

📑正規表現エンジンの分類

正規表現技術入門 p. 56より

regex-applicativeの場合は…?

😕どちらでもなさそう?

regex-applicativeの実際の実装

regex-applicativeの実際の実装(続き)

類似のライブラリーとの比較を軽く

各種パーサーコンビネーター

VerbalExpressions

まとめ