3

私はタイプを持っています

data Phase = PhaseOne
           | PhaseTwo
           | PhaseThree deriving Enum

各フェーズで実行する 5 つの操作

  • read
  • write
  • validate
  • evalStatus
  • update

型クラスを作成しようとし始めました。問題は、それらがすべて同じタイプであることです。次のようなことができるようになりたいです

instance MyClass PhaseThree where
  read a = ...

また、戻り値の型をオーバーロードする必要があります。

私は型クラスが私が望むものではないことを知っています。しかし、私は自分がやりたいことをする方法がわかりません。私は GADT を考えましたが、各インスタンスを個別のファイルに入れる必要があるため、それは正しくありません。

どのメカニズムを調査する必要があるかについてアドバイスをお願いします。十分な情報を提供しましたか?

4

2 に答える 2

3

少し反転させることをお勧めします。

data Phase = Phase {
    read :: String -> Foo,
    write :: Foo -> IO (),
    validate :: Foo -> Bool,
    evalStatus :: IO (),
    update :: Foo -> Foo
}

phaseOne, phaseTwo, phaseThree :: Phase

(または、明示的なレコードへのクラスの同様の再調整)。

于 2012-07-03T02:46:46.123 に答える
2

上記の私のコメントを詳しく説明すると、操作をサポートするクラスで 3 つの異なる型を使用したい場合は、クラス メソッドを使用して のEnumような機能を組み込むことができます。succ

Doneまた、プレースホルダーとしてタイプを提供する必要がありますsucc PhaseThree

{-# LANGUAGE MultiParamTypeClasses , FunctionalDependencies #-}
data PhaseOne = PhaseOne
data PhaseTwo = PhaseTwo
data PhaseThree = PhaseThree

data Done = Done

class YourClass p0 p1 | p0 -> p1 where
    succ :: p0 -> p1
    -- read :: ...
    -- write :: ...etc

instance YourClass PhaseOne PhaseTwo where
    succ PhaseOne = PhaseTwo
    -- read = ...

instance YourClass PhaseTwo PhaseThree where
    succ PhaseTwo = PhaseThree

instance YourClass PhaseThree Done where
    succ PhaseThree = Done

、などのメソッドSuccから機能を分離し、 2 つのクラスを作成することもできます。戻り値は多態的である可能性があります。readwrite

succsucc PhaseThreeエラーをスローするだけなので、元の投稿された定式化は恐ろしいものです。アプリケーションで型システムを機能させることができれば、それが理想です。

于 2012-07-03T18:16:00.250 に答える