提升的数据类型和类实例

时间:2012-06-12 20:23:17

标签: haskell type-kinds

提升的数据类型具有固定数量的类型,这些类型是提升数据类型的成员。在这个封闭的世界中,支持在没有字典的字典中调用类型类的函数是否有意义?

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}

data DataType = Constructor

data DataTypeProxy (e :: DataType) = DataTypeProxy

class Class (e :: DataType) where
  classFunction :: DataTypeProxy e -> IO ()

-- this is the only instance that can be created
instance Class 'Constructor where
  classFunction _ = return ()

-- adding the Class constraint fixes the build break
-- disp :: Class e => DataTypeProxy e -> IO ()
disp :: DataTypeProxy e -> IO ()
disp = classFunction

main :: IO ()
main = disp (DataTypeProxy :: DataTypeProxy 'Constructor)

这个人为的例子在GHC负责人中不起作用。这并不奇怪,但似乎DataKind扩展可能使这成为可能。

test.hs:18:8:
    No instance for (Class e) arising from a use of `classFunction'
    Possible fix:
      add (Class e) to the context of
        the type signature for disp :: DataTypeProxy e -> IO ()
    In the expression: classFunction
    In an equation for `disp': disp = classFunction

1 个答案:

答案 0 :(得分:4)

没有。允许这样做意味着幻像数据类型需要在运行时用额外的类型信息“标记”,并且会产生歧义。

data DataType = Constructor | SomethingElse

data DataTypeProxy (e :: DataType) = DataTypeProxy 
...
instance Class 'SomethingElse where
   classFunction _ = putStrLn "hello world"

instance Class 'Constructor where
   classFunction _ = return ()

disp :: DataTypeProxy e -> IO ()
disp = classFunction

main = disp DataTypeProxy

这个程序应该做什么?它应该编译吗?如果没有,那么通过构造函数添加到类型中,我们获取了一个您想要编译的程序,并生成了一个不需要的程序。如果它不应该编译,那么它有两个有效的行为。

main = disp (DataTypeProxy :: DataTypeProxy 'Constructor)

只有一种可能的解释......但它要求你以幻影类型发送。也就是说,

main = disp (DataTypeProxy :: DataTypeProxy 'SomethingElse)

是术语级别的相同程序,但具有不同的行为。这基本上打破了所有漂亮的属性,如参数化。基于类的基于类的调度是对此的解决方案,因为范围中的哪些实例以可预测(并且语义指定)的方式影响程序行为。