1

我想要一个状态单子,我在其中保存一个模式列表。

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

但是,我有两个要求:

  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 aState a. 这意味着没有Mode String并且Mode ()可以在一个国家内共存。

尝试 2 :, 类型类

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

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

但是,现在我不知道如何在给定的运行时构建模式complFaction. 似乎类型类的实例必须在编译时定义。

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

有解决方法吗?

4

1 回答 1

4

如果模式支持固定的 API,您可以使用存在类型来隐藏它们的表示类型。例如

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

然后实现一个ModeLike只有类型支持的操作的Mode类。您的第二次尝试接近此。

由于类型类实例是打开的,因此您无需更改代码即可添加新实例。

然而,如果你有一个完全动态的系统——即你不能枚举可能模式的类型——你将不得不使用动态类型作为实例之一。

于 2012-05-08T11:53:39.690 回答