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

I would like to have a State Monad, where I keep a list of modes.

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

However, I have two requirements:

  • Mode needs to be a parametrized with a type.
  • Mode can be built on run time.
  • Here is how I tried to convince GHC:

    Attempt 1 , with a data type

    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
    }
    

    Good.. however, this is not useful for me, since every mode has to be of type Mode a inside a State a . Meaning that no Mode String and Mode () can co-exist within a State.

    Attempt 2 :, type class

    class Mode a where
           complF :: String -> IO [String] 
           action :: State -> String -> X a
    
    data State = S {
           modes :: (Mode a) => [a]
    }
    

    But, now I don't know how to build a mode in run time given complF and action . It seems that instances of type classes must be defined at compile time.

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

    Is there a workaround?


    If modes support a fixed API, you can use an existential type to hide their representation type. Eg

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

    and then implement a class ModeLike that has only those operations supported by Mode types. Your 2nd attempt is close to this.

    Since type class instances are open, you add new instances without changing your code.

    If you have, however, a fully dynamic system -- ie you cannot enumerate the types that will be possible modes - you will have to use a dynamic type as one of the instances.

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

    上一篇: 使用关联的类型同义词自动推导Data.Vector.Unbox

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