2017-02-25 71 views
4

我想弄清楚类型类和GADTS之间的差异,特别是在使用-XMultiParamTypeClasses扩展名时。了解何时使用类型类或GADT?

似乎都具有类似用途:

class MyClass a b where 
    f :: a -> b -> Bool 

instance MyClass String String where 
    f s1 s2 = ... 

instance MyClass Int Int where 
    f i1 i2 = ... 

data Gadt a where 
    F :: String -> String -> Bool 
    F2 :: Int -> Int -> Bool 

到目前为止,唯一的区别我真正看到的是,GADT的使能功能型接口有一个灵活的数字参数:

data Gadt a where 
    PassTwoArgs :: String -> String -> Gadt Bool 
    PassOneArgs :: String -> Gadt Bool 

myFunction :: Gadt a -> a 
myFunction (PassTwoArgs s1 s2) = ... 
myFunction (PassOneArgs s1) = ... 

虽然这对于类型类来说并不容易。

是否有任何其他差异或使用情况使用其中一种?

回答

6

如果您有,您可以随时添加新实例。

如果您使用GADT,您将拥有永久修复的数据结构。你永远不能增加新的案例,而不会改变原来的定义。但是,正如你所看到的那样,它更加灵活。

真的,它们是针对不同的用例。当你希望能够对许多不同的数据类型进行操作时,这些类就是用来处理这些数据类型的,而这些数据类型之间没有任何关系。 (例如,您可以在IntString上执行(==),但这些类型不是非常相似。)GADT适用于您想要一种类型,但其某些类型参数会告诉您一些相关信息。规范示例是GADT代表某种编程语言中的表达式,并且您希望使用类型系统来强制执行其他语言的类型系统。

什么类不是类似于我们在面向对象编程中使用的“类”。 ;-)请把所有这些想法都放在你的大脑中。

2

如果您需要模式匹配,请使用(G)ADT。如果您需要第三方来实现您的界面,请使用类型类。

我的直觉是尽可能使用类型类;如果我绝对需要模式匹配,那么我会达到(G)ADT。我通常不需要它。