Tôi có đoạn code sau, và tôi sẽ như thế này để thất bại kiểm tra kiểu:Làm cách nào để sử dụng các hạn chế bị hạn chế với GADT?
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
import Control.Lens
data GADT e a where
One :: Greet e => String -> GADT e String
Two :: Increment e => Int -> GADT e Int
class Greet a where
_Greet :: Prism' a String
class Increment a where
_Increment :: Prism' a Int
instance Greet (Either String Int) where
_Greet = _Left
instance Increment (Either String Int) where
_Increment = _Right
run :: GADT e a -> Either String Int
run = go
where
go (One x) = review _Greet x
go (Two x) = review _Greet "Hello"
Ý tưởng là mỗi mục trong GADT có lỗi liên quan, mà tôi đang mô hình hóa với một Prism
vào một số cấu trúc lớn hơn. Khi tôi "giải thích" GADT này, tôi cung cấp một loại cụ thể cho e
có các phiên bản cho tất cả các số này là Prism
s. Tuy nhiên, đối với từng trường hợp riêng lẻ, tôi không muốn có thể sử dụng các cá thể không được khai báo trong ngữ cảnh liên quan của hàm tạo.
Mã trên phải là một lỗi, vì khi tôi khớp mẫu trên Two
Tôi nên tìm hiểu rằng tôi chỉ có thể sử dụng Increment e
, nhưng tôi đang sử dụng Greet
. Tôi có thể thấy lý do tại sao thao tác này hoạt động - Either String Int
có một phiên bản cho Greet
, vì vậy mọi thứ đều kiểm tra.
Tôi không chắc cách tốt nhất để khắc phục điều này là gì. Có lẽ tôi có thể sử dụng entailment từ Data.Constraint
hoặc có thể có một mẹo với các loại xếp hạng cao hơn.
Bất kỳ ý tưởng nào?
Để mở rộng điều này, Ed là đúng - phần quan trọng là bạn cung cấp 'e' tại điểm * gọi * chạy, thay vì định nghĩa' run'. – ocharles