鉴于其主体功能,创建一个类型类的实例(或解决方法)

我想有一个国家Monad,我保留一个模式列表。

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

但是,我有两个要求:

  • 模式需要用类型进行参数化。
  • 模式可以在运行时建立。
  • 以下是我试图说服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
    }
    

    好..但是,这对我来说没有用,因为每个模式都必须是State a Mode a State a 。 意思是没有Mode StringMode ()可以在一个状态内共存。

    尝试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 :: ..
    

    有没有解决方法?


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

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

    然后实现一个仅具有Mode类型支持的操作的ModeLike类。 你的第二次尝试就是接近这个。

    由于类型实例已打开,因此可以在不更改代码的情况下添加新实例。

    但是,如果你有一个完全动态的系统 - 也就是说你不能枚举将成为可能模式的类型 - 你将不得不使用动态类型作为其中一个实例。

    链接地址: http://www.djcxy.com/p/86097.html

    上一篇: Given its body functions, create an instance of a type class (or workaround)

    下一篇: explanation for "illegal type synonym family"