Vấn đề là bạn cần một định lượng phụ thuộc mà Haskell hiện thiếu. I E. phần (x : A)(xs : Vec A (suc n)) → ...
không thể hiển thị trực tiếp. Bạn có lẽ có thể nấu một thứ gì đó bằng cách sử dụng đơn, nhưng nó sẽ thực sự xấu xí và phức tạp.
Tôi chỉ sẽ xác định
delete ∷ Eq a ⇒ a → Vec a (S n) → Maybe (Vec a n)
và chịu tốt với nó. Tôi cũng sẽ thay đổi thứ tự của các đối số thành Vec
để có thể cung cấp Applicative
, Traversable
và các trường hợp khác.
Thực ra, không. Để xác định delete
bạn chỉ cần cung cấp một chỉ số mà tại đó để xóa:
{-# LANGUAGE GADTs, DataKinds #-}
data Nat = Z | S Nat
data Index n where
IZ :: Index n
IS :: Index n -> Index (S n)
data Vec n a where
Nil :: Vec Z a
(:-) :: a -> Vec n a -> Vec (S n) a
delete :: Index n -> Vec (S n) a -> Vec n a
delete IZ (x :- xs) = xs
delete (IS n) (x :- (y :- xs)) = x :- delete n (y :- xs)
Lưu ý rằng x ∈ xs
là gì khác hơn là một chỉ số đa dạng gõ.
Đây là một giải pháp với độc thân:
{-# LANGUAGE GADTs, DataKinds, PolyKinds, KindSignatures, UndecidableInstances, TypeFamilies, RankNTypes, TypeOperators #-}
infixr 5 :-
data Nat = Z | S Nat
data family Sing (x :: a)
data instance Sing (b :: Bool) where
STrue :: Sing True
SFalse :: Sing False
data instance Sing (n :: Nat) where
SZ :: Sing Z
SS :: Sing n -> Sing (S n)
type family (:==) (x :: a) (y :: a) :: Bool
class SEq a where
(===) :: forall (x :: a) (y :: a). Sing x -> Sing y -> Sing (x :== y)
type instance Z :== Z = True
type instance S n :== Z = False
type instance Z :== S m = False
type instance S n :== S m = n :== m
instance SEq Nat where
SZ === SZ = STrue
SS n === SZ = SFalse
SZ === SS m = SFalse
SS n === SS m = n === m
data Vec xs a where
Nil :: Vec '[] a
(:-) :: Sing x -> Vec xs a -> Vec (x ': xs) a
type family If b x y where
If True x y = x
If False x y = y
type family Delete x xs where
Delete x '[] = '[]
Delete x (y ': xs) = If (x :== y) xs (y ': Delete x xs)
delete :: forall (x :: a) xs. SEq a => Sing x -> Vec xs a -> Vec (Delete x xs) a
delete x Nil = Nil
delete x (y :- xs) = case x === y of
STrue -> xs
SFalse -> y :- delete x xs
test :: Vec '[S Z, S (S (S Z)), Z] Nat
test = delete (SS (SS SZ)) (SS SZ :- SS (SS (SS SZ)) :- SS (SS SZ) :- SZ :- Nil)
Ở đây chúng ta chỉ Vec
s bởi danh sách các yếu tố của họ và lưu trữ độc thân như các yếu tố của vectơ. Chúng tôi cũng định nghĩa SEq
là một lớp kiểu có chứa một phương thức nhận hai đơn và trả về một bằng chứng về sự bình đẳng của các giá trị mà chúng thúc đẩy hoặc bất bình đẳng của chúng. Tiếp theo, chúng tôi định nghĩa họ loại Delete
giống như thông thường delete
cho danh sách, nhưng ở cấp loại. Cuối cùng trong delete
thực tế, chúng tôi khớp mẫu trên x === y
và do đó tiết lộ liệu x
có bằng y
hay không, điều này làm cho tính toán gia đình loại.
Bạn có thể sử dụng 'Either', với' Left xs' biểu thị vectơ ban đầu không có giá trị nào được xóa và 'Right ...' đại diện cho một vectơ mới với 'x' bị loại bỏ. – chepner
Tôi không khuyên bạn nên sử dụng Haskell để tìm hiểu các loại phụ thuộc. Haskell không bao giờ được thiết kế như một ngôn ngữ phụ thuộc (mặc dù tiến trình họ đang làm là đáng chú ý) và các thủ thuật như singletons chẳng là gì ngoài hacks để giúp mô phỏng các kiểu phụ thuộc. Tìm hiểu các khái niệm trong một ngôn ngữ DT như Agda hoặc Idris đầu tiên - sau đó bạn sẽ tìm thấy nó dễ dàng hơn nhiều để hiểu các mã hóa trong Haskell. –
Người ta cũng có thể xem xét khả năng giao diện được chọn cho các chức năng thư viện Haskell là kết quả của và được dự định chỉ tốt cho lập trình theo cách không phụ thuộc.Thay vì chuyển giao diện đó, thay vào đó, người ta có thể nghĩ hai lần về nó. Tôi, cho một, sẽ không bao giờ thực hiện xóa. Tôi sẽ thực hiện các view mà inverts chèn. – pigworker