haskell - GADT - 应用和用处?

标签 haskell gadt

我正在使用 learnyouahaskell 来介绍 GADT,并且我对它们可能的用途很感兴趣。据我了解,它们的主要特点是允许显式类型设置。

如:

data Users a where 
  GetUserName :: Int -> Users String
  GetUserId :: String -> Users Int

usersFunction :: Users a -> a 
usersFunction (GetUserName id) 
   | id == 100      = "Bob"
   | id == 200      = "Phil"
   | otherwise      = "No corresponding user"
usersFunction (GetUserId name)
   | name == "Bob"      = 100
   | name == "Phil"     = 200
   | otherwise          = 0

main = do
   print $ usersFunction (GetUserName 100)

除了在处理这些数据类型时添加额外的类型安全性之外,GADT 的其他用途还有哪些?

最佳答案

Glambda

Richard Eisenberg 在 glambda 中为 GADT 提供了非常令人信服的案例一个简单类型的 lambda 演算解释器,它使用 GADT 来确保无法构建错误类型的程序。 Phil Wadler 有类似且更简单的东西 here ,从中获取以下样本

data Exp e a where
  Con :: Int -> Exp e Int
  Add :: Exp e Int -> Exp e Int -> Exp e Int
  Var :: Var e a -> Exp e a
  Abs :: Typ a -> Exp (e,a) b -> Exp e (a -> b)
  App :: Exp e (a -> b) -> Exp e a -> Exp e b

这个想法是,表达式的类型(在解释器中)被编码为 Haskell 程序中表示的表达式类型。

根据长度输入向量

通过使用 GADT,我们可以添加一个幻像类型,告诉我们跟踪我们拥有的向量的长度。 This包有一个很好的实现。这可以通过多种方式重新实现(例如使用 GHC.TypeLits 类型级自然数)。有趣的数据类型(从链接的包的源复制)是

data Vector (a :: *) (n :: Nat)  where
  Nil  :: Vector a Z
  (:-) :: a -> Vector a n -> Vector a (S n)

然后,我可以编写一个安全版本的 head'::Vector a (S n) -> a

约束

我没有一个很好的例子来证明它的用处,但是您可以在 GADT 中对各个构造函数添加约束。您在构造函数上添加的约束在您构造某些内容时会强制执行,并且在您进行模式匹配时可用。这让我们可以做各种有趣的事情。

data MyGADT b where
  SomeShowable :: Show a => a -> b -> MyGADT b     -- existential types!
  AMonad :: Monad b => b -> MyGADT b

关于haskell - GADT - 应用和用处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39930569/

相关文章:

haskell - GADT 和 ghc 7.8.2 上的显式 forall

haskell - 从一系列较小的类型类实例中推断出通用类型类实例?

haskell - 访问 'data' 的下一个元素

Haskell 懒惰 Bytestring 的话不懒惰吗?

Haskell 获取数据构造函数的类型

haskell - 类型级列表的行多态相等性

haskell - 如何设置 haskell-mode 来生成标签?

haskell - 如何在镜头样式单板库中为更高种类的类型实现孔和上下文?

Haskell GADTs - 为黎曼几何制作类型安全的张量类型

haskell - Data.Map中键/值关系的静态保证