haskell-jp / questions #104 at 2023-06-25 06:57:06 +0900

haskellの事をAIに質問していたら、sha256な文字列に出会いました。
ask AI この鬼のように長いsha256な文字表現を短縮したいです。イメージは
sed 's/hexDigit x 64/SHA256/g'
これをparsecで実現するには、どうしたら良いのでしょうか?
ParsecについているhexDigitってパーサーを使えばそのものズバリ1桁の16進数にマッチさせることができるので、それを replicateM_ などで64回繰り返せばそうした文字列にマッチするパーサーができます。
で、置換すると言うことなので「マッチしたら( hexDigit の結果を無視して)当該の文字列に置き換える」ために <$ を使って
import Control.Applicative
import Text.Parsec.Char
import Control.Monad

p = "SHA256" <$ (replicateM_ 64 hexDigit)

と書けば、「64桁の16進数文字列を SHA256 という文字列に置き換える」パーサーができます。

ただし、難しいのがここからで、Parsecを始め一般にパーサーコンビネーターライブラリーは、「文字列の*先頭から*マッチする」ことに特化しているので、これだけでは例として挙げていた
libHSgnuplot-0.5.7-35e9d90b027708a768a475efa9832c80027beea2c362a5c163bd3e513145d115.a

みたいな文字列にはマッチしません。
「問題の16進数の文字列の手前までは別途処理する」という場合はこのままでよいのですが、これで不十分だという場合は、部分文字列にマッチさせるよう書き換えるか、今回の場合、問題のファイル名の形式がはっきりしているようなのでそれに合わせて先頭からパースするパーサーに変える必要があります。

前者の「部分文字列にマッチさせるよう書き換える」のを自動でやってくれるライブラリーとして、parsec向けではないんですが、
https://hackage.haskell.org/package/replace-attoparsechttps://hackage.haskell.org/package/replace-megaparsec というのがお勧めです。
ちなみに、64桁の16進数だからと言ってSHA256とは限らないかと。 https://qiita.com/KEINOS/items/c92268386d265042ea16 曰く出力が32バイト(16進数で64桁)になるハッシュ関数は他にもたくさんありますし。
実際にGHCやcabalがどうしているかは私も知らない所なので恐縮ですが...
色々な解説、ありがとうございました。
私も、投稿した後少し調べてみました。
sed = try p <|> anyChar ; sed
という方法が使えないかと。うんと悩んでみます。
涙の数だけ、強くなれるよ、がモットーです。