私は特定のデータ構造の2つの実装の間で引き裂かれ、何が正しい/標準であるかについてHaskellコミュニティからの入力をいただければ幸いです。
データ型
たとえば、複数のサーバーをnullaryデータコンストラクターとして定義するADT「サーバー」を考えてみましょう。
data Server = Server1
| Server2
| Server3
さて、これらのサーバーのそれぞれについて、(とりわけ)IPアドレスを取得する機能が必要です。これらを静的にコーディングできると仮定すると、いくつかの関数「getURL」とパターンマッチを使用できます。
getUrl :: Server -> String
getUrl Server1 = "192.168.1.1"
これで、サーバーを使用するすべての関数で、サーバーをタイプに入れてgetURLを呼び出すことができます。
serverStuff :: Server -> IO ()
このメソッドには、getURLで多くのパターンマッチングが行われるという犠牲を払って、単純な非ポリモーフィック関数の利点があるようです。さらに、プログラマーがサーバーを追加したが、getURLにパターンを追加するのを忘れた場合、-Wallでコンパイルしない限り、警告なしにランタイムエラーが発生します。
型クラス
タイプクラスで同じ問題を攻撃して、マルチコンストラクターADTをサーバーに固有のADTのセットに分割し、URLのタイプクラスを作成できます。
data Server1 = Server1
data Server2 = Server2
data Server3 = Server3
class Server a where
getUrl :: a -> String
instance Server Server1 where
getUrl Server1 = "192.168.1.1"
など。これで、以前使用した単純な非ポリモーフィック関数の代わりに、次のようなものを作成する必要があります。
serverStuff :: Server a => a -> IO ()
アドホック多相性(関数の特殊化など)の影響に対処します。
明るい面として、typeclassメソッドは拡張が簡単で、パターンマッチングをより小さなチャンクに分割し、グループ化されたサーバー(data ServerCenter1 = Server1 | Server2 | Server3
)などのより高度な抽象化を可能にします。 getUrlを宣言すると、インスタンスを作成するときに少なくともその決定を行う必要があります。
だから、私は引き裂かれていますが、物事を行うためのより良い方法としてインスタンスに傾いています。この問題を処理するための標準的な方法はありますか、それとも「クリーンに見えるものは何でも」タイプのものですか?