1

モードのリストを保持するステートモナドが欲しいのですが。

data State = S { 
      modes :: [Mode]
}

ただし、2つの要件があります。

  1. モードはタイプでパラメータ化する必要があります。
  2. モードは実行時に構築できます。

これが私がGHCを説得しようとした方法です:

試行1、データ型を使用

data Mode a = Mode { 
      complF :: String -> IO [String]
      action :: State -> String -> X a
}

data State a = S { 
      modes :: [Mode a]
}

initState :: (String -> IO [String]) -> (State -> String -> X a) -> State a
initState c a = {
      modes = [buildMode c a]
}

buildMode :: (String -> IO [String]) -> (State -> String -> X a) -> Mode a
buildMode c a = {
       complF = c
     , action = a
}

良い..しかし、すべてのモードは。Mode a内のタイプでなければならないので、これは私には役に立ちませんState aMode Stringいいえ、Mode ()州内で共存できることを意味します。

試行2:、型クラス

class Mode a where
       complF :: String -> IO [String] 
       action :: State -> String -> X a

data State = S {
       modes :: (Mode a) => [a]
}

complFしかし、今は与えられた実行時間でモードを構築する方法がわかりませんaction。型クラスのインスタンスはコンパイル時に定義する必要があるようです。

instance Mode DefaultMode where
       complF :: .. 
       action :: ..

回避策はありますか?

4

1 に答える 1

4

モードが固定 API をサポートしている場合、存在型を使用して表現型を非表示にすることができます。例えば

data State = S { 
  modes :: forall a . ModeLike a => [Mode a]
}

ModeLike次に、型でサポートされている操作のみを持つクラスを実装しModeます。2 回目の試行はこれに近いです。

型クラスのインスタンスは開いているため、コードを変更せずに新しいインスタンスを追加できます。

ただし、完全に動的なシステムを使用している場合 (つまり、可能なモードになる型を列挙できない場合)、インスタンスの 1 つとして動的型を使用する必要があります。

于 2012-05-08T11:53:39.690 に答える