質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.63%

haskell 正規表現

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 662

mightyMask

score 125

正規表現を抽象化したコードを書きたくて、以下のようなものができました。

data Regex 
    = Literal String                        -- 完全一致
    | AnyChar                               -- 何かしら1文字 「.」
    | Not Regex                            -- 否定 「^」
    | And {a::Regex, b::Regex}              -- aの次にb
    | Or  {a::Regex, b::Regex}              -- aまたはb 「|」
    | Repeat {range::[Int], element::Regex} -- elementがrangeのいずかの個数

superPosition :: Regex -> Regex             -- 0回か1回 「?」
superPosition regex = Repeat [0,1] regex

some :: Regix -> Regix                      -- 1回以上繰り返し 「+」
some regex = Repeat [1..] regex

oneOrMore :: Regex -> Regex                 -- 0回以上繰り返し 「*」
oneOrMode regex = Repeat [0..] regex

match :: Regex -> String -> Bool
match (Literal literal)      string = literal == string
match (AnyChar)              string = length string == 1
match (Not regix)            string = not $ match regix string
-- TODO -- match (And a b)              string =
match (Or  a b)              string = match a || match b
-- TODO -- match (Repeat range element) string = 

 解決したい問題点

  • TODOの部分の実装は今の自分の力でも無理やり実装しようと思えばできるけど、効率の良いhaskellらしいコードにするにはどんなやり方があるか。

  • someとかの関数とOrとかのコンストラクタが利用側では同じように使えるべきだが、キャメルケースとパスカルケースで違う見た目になっている。

  • superPositionとかoneOrMoreという名前付けが他のものと一貫性が取れてない。もっと良い名前がないか?

  • someとかorとかの名前付けだと利用側で名前衝突が起こる可能性があるかも?ないかも?初心者だからこの名前付けが良いのか悪いのかも分からない。

  • rangeに負の整数を指定できてしまう

他にも私には分からない問題点があると思うので、そちらにもリファクタリングやマサカリをお願いします。
「regexは他にあるから車輪の再発明だ」っていうマサカリだけは無しでお願いします。
勉強のために車輪の再発明をしています。

そもそもRegexはString -> Boolの型シノニムとした方がいいんですかね?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

- TODOの部分の実装は今の自分の力でも無理やり実装しようと思えばできるけど、効率の良いhaskellらしいコードにするにはどんなやり方があるか。

マッチの部分は(手続きプログラミングでも)オートマトンを使って実装するのが定番だと思います。オートマトンについてはすみませんが他を参考にしてください。

someとかの関数とOrとかのコンストラクタが利用側では同じように使えるべきだが、キャメルケースとパスカルケースで違う見た目になっている。

or = Or

として or を定義することができます。

superPositionとかoneOrMoreという名前付けが他のものと一貫性が取れてない。もっと良い名前がないか?

いい案が思い付かないのでノーコメントで。

someとかorとかの名前付けだと利用側で名前衝突が起こる可能性があるかも?ないかも?初心者だからこの名前付けが良いのか悪いのかも分からない。

名前空間があるので問題ないと思います。

例えばこれが Regex モジュールだった場合、利用者は Regex.some という形で参照することができます。(他の方法もあります。)

rangeに負の整数を指定できてしまう

Int の代わりに Word で非負整数を表します。

投稿

コミュニティ
  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/24 18:31

    そもそもこのような実装にするのと、`String->Bool`の型シノニムとして実装するのはどちらの方が良い実装だと思いますかね?

    キャンセル

  • 2018/11/24 22:11

    正規表現をパースしたトークン列としては

    ```haskell
    type Regex = [Token]

    data Token
    = Char (Prelude.Char -> Bool)
    | Or Regex Regex
    | Repeat Word Regex
    ```

    こんな雰囲気にする気がします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る