了解何时使用类型类或GADT?

时间:2017-02-25 13:30:09

标签: haskell typeclass gadt

我试图找出类型类和GADTS之间的差异,尤其是在使用-XMultiParamTypeClasses扩展时。

两者似乎都有类似用途:

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) = ...

虽然使用类型类并不容易。

是否有任何其他差异或用例使用一个而不是另一个?

2 个答案:

答案 0 :(得分:7)

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

如果您使用GADT,则您拥有永久固定的数据结构。您无法在不更改原始定义的情况下向其添加新案例。但是,正如您所说,它更灵活。

实际上,它们适用于不同的用例。当您希望能够对许多不同的数据类型执行某些操作时,这些类就是彼此无关的。 (例如,您可以在(==)IntString,但这些类型不是很相似。)GADT适用于您想要一种类型,但它的一些类型参数告诉你一些关于它的东西。规范示例是GADT表示某种编程语言中的表达式,并且您希望使用 Haskell 类型系统来强制执行其他语言的类型系统。

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

答案 1 :(得分:2)

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

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