Tôi đang cố gắng nắm bắt GADTs
và tôi đã xem GADTs example trong hướng dẫn sử dụng của GHC. Theo như tôi có thể nói, nó có thể làm điều tương tự với MultiParamTypeClasses
:GADTs so với MultiParamTypeClasses
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, UndecidableInstances #-}
class IsTerm a b | a -> b where
eval :: a -> b
data IntTerm = Lit Int
| Succ IntTerm
data BoolTerm = IsZero IntTerm
data If p a = If p a a
data Pair a b = Pair a b
instance IsTerm IntTerm Int where
eval (Lit i) = i
eval (Succ t) = 1 + eval t
instance IsTerm BoolTerm Bool where
eval (IsZero t) = eval t == 0
instance (IsTerm p Bool, IsTerm a r) => IsTerm (If p a) r where
eval (If b e1 e2) = if eval b then eval e1 else eval e2
instance (IsTerm a c, IsTerm b d) => IsTerm (Pair a b) (c, d) where
eval (Pair e1 e2) = (eval e1, eval e2)
Lưu ý rằng chúng ta có các nhà thầu cùng chính xác và mã chính xác tương tự cho eval
(lây lan qua các định nghĩa ví dụ) như trong Ví dụ GADTs
của GHC.
Vì vậy, tất cả các fuzz về GADTs
là gì? Tôi có thể làm gì với GADTs
mà tôi không thể thực hiện với MultiParamTypeClasses
không? Hay họ chỉ cung cấp một cách súc tích hơn để làm những việc mà tôi có thể làm với MultiParamTypeClasses
thay vào đó?
Trong mẫu của bạn, bạn có thể xây dựng 'If (Lit 3) (IntTerm 1) (IntTerm 2)'. Xem xét sử dụng 'dữ liệu Nếu a = Nếu BoolTerm a'. – ony
GADT không cung cấp bất kỳ thứ gì không thể mô phỏng được bằng các loại tồn tại và loại bình đẳng. Nhưng ví dụ cụ thể của bạn không phải là một ví dụ về điều này. – augustss
GADT bị đóng tại thời điểm định nghĩa, có thể là một sự khác biệt rất lớn. –