• 作成:
  • 更新:

Haskellの文字列型同士の変換が欲しい場合はconvertibleかstring-conversionsを使うと良い感じです

自作ライブラリのstring-transformの改善を考えていました

自作ライブラリの、 string-transform が微妙だなと思いはじめました。

公開時の考えはだいたいこの記事に書いてありました。 Amazon S3の問題はMultipart Uploadで解決しそう, haskellの文字列の変換をわかりやすくするstring-transformを公開しました - ncaq

string-transform関連記事

命名規則を変えたい

何もなく物思いに耽る時間があって考えてたのですが、 toByteStringLazyは微妙すぎます。 toLazyByteStringにするべき。 LazyであるのはByteString型という名詞であってto変換操作という動詞ではない。つまり英語の文脈に沿えばLazyは形容詞であって副詞ではない。 ShortByteStringの存在もそれを示唆しています。

なぜこのような並びにしたのかと言うと、 ByteStringとかTextとかは、 Data.ByteString.LazyのようにLazyStrictが後ろに来るので、その順番に素直に従ったからです。しかし係り受け構造を考えると、前に付けた方が良かったですね。

しかし、 ShortByteStringは一つの分割不能な型を意味するので、 to + 型名 + 評価方法という分割であるとするならば一応筋は通ってます。

他にも色々改善案を考えていました。

型クラスを1つにする

型クラスを小さくするべきな理由は、部分的にしかメソッドを実装できなくて、インスタンスに出来なくなるデータ型を少なくするためです。

このモジュールは他の関数を合成して自然に関数を作り出せるため、型クラスを分ける強い理由はあまり無いのではないかと思いました。型クラスを纏めると利用側で型制約を書くことが楽になります。

from系の関数を作る

変換元のデータ型はハッキリしていますが、変換先のデータ型がよく分からないので適当に推論してほしいことがあります。

from系のメソッドを型クラスに新しく増やしたいですね。

関数名を短くする

toByteStringLazyにしろ、 toLazyByteStringにしろ、長いので短縮したい時があります。 toLBSとでも書きたいですね。

string-conversionsはさっきまで自分で考えていた改善案が全て実装されてました

関数名なるべく衝突させたくなくて、 Hoogle検索していて気がついたのですが、 string-conversions はこれらの改善案が全て実装されています。

よって自作ライブラリの価値は無くなりました。

実は以前からこのライブラリの存在は知っていました。しかし、以前このライブラリを見た時は、型クラスの返り値型推論をガンガン使ってるので、コードの可読性が悪くなることを懸念していましたが、今見るとさほど高度な機能使ってないですね。これはGHCなどのツールチェインの更新で、ある種のGHC拡張を自然に使えるようになったからか? それとも私のHaskell力が上がってこれを複雑だと思わなくなったからか? 理由は謎ですがどちらにせよ今の私にとってこれはもはや複雑ではありません。

何故知っていたのか記事を探ったのですが、 Haskellによるwebスクレイピングの方法をdic-nico-intersection-pixivを例に書く - ncaq で、 Haskell の (文字列) 変換パッケージ (convertible, convert, conversion) - Qiita (リンク切れ) に触れていて、これで知ったんだろうなあと思いました。

また、単純な形式を使いたい場合でもこれを使わない理由はありません。 Data.String.Conversions.Monomorphic に単一化された巻数が実装されているので、やっていることを分かりやすくしたい時はcs関数ではなく、このモジュールの関数を使えば良さそうです。

fromも短い形式もサポートしています。

string-convertは微妙

string-convert は良くなさそう。効率の良くないStringを経由していてるからです。うまいことインライン展開されたら中間リストが消されるかもしれませんが。他のライブラリを使えば直接変換されるのに、わざわざこれを使いたくないという感情があります。

convertibleは万能選手

何で他のライブラリを複雑だと思ったのか完全に理解しました。 convertible を見てそのインスタンスの爆発を見たからですね。

このライブラリは文字列同士だけではなく、例えばInt -> Doubleなどの変換もサポートしています。

文字列だけのサポートで言っても、 Builder系の変換をサポートしています。

convert関数は失敗する危険性が割と高そうですが、まあ厳密に考えると文字列同士の変換もUTF-8でなければエラーになりますね。 ByteStringを文字列としてみた場合の話です。

これさえあれば他に何も要らないですね。

まとめ

文字列の変換だけが欲しかったり、単一化された関数が欲しい場合は、 string-conversions を使います。

万能選手が欲しい場合は、 convertible を使います。

今後基本的にはconvertibleを使っていくと思います。試しに書き換えてみたらこれで特に問題が起きなかったので。この2つは衝突する存在ではないので、両方使っても特に問題は起きないと思います。