Một sự thật đúng đắn về phép nối là nếu tôi biết bất kỳ hai biến nào trong phương trình:
a ++ b = c
Sau đó tôi biết thứ ba.
Tôi muốn nắm bắt ý tưởng này trong concat của riêng tôi để tôi sử dụng một phụ thuộc chức năng.
{-# Language DataKinds, GADTs, FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, PolyKinds, TypeOperators, UndecidableInstances #-}
import Data.Kind (Type)
class Concatable
(m :: k -> Type)
(as :: k)
(bs :: k)
(cs :: k)
| as bs -> cs
, as cs -> bs
, bs cs -> as
where
concat' :: m as -> m bs -> m cs
Bây giờ tôi gợi ý danh sách không đồng nhất như vậy:
data HList ( as :: [ Type ] ) where
HEmpty :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
Nhưng khi tôi cố gắng khai báo những điều này vì Concatable
tôi có một vấn đề
instance Concatable HList '[] bs bs where
concat' HEmpty bs = bs
instance
( Concatable HList as bs cs
)
=> Concatable HList (a ': as) bs (a ': cs)
where
concat' (HCons head tail) bs = HCons head (concat' tail bs)
Tôi không đáp ứng sự phụ thuộc chức năng thứ ba của tôi. Hay đúng hơn là trình biên dịch tin rằng chúng tôi không. Điều này là do trình biên dịch tin rằng trong trường hợp thứ hai của chúng tôi, nó có thể là trường hợp đó bs ~ (a ': cs)
. Và nó có thể là trường hợp nếu Concatable as (a ': cs) cs
.
Làm cách nào tôi có thể điều chỉnh các phiên bản của mình để cả ba phụ thuộc đều hài lòng?
bs
và cs
, và chúng tôi muốn khai thác quỹ, tức là chúng tôi muốn xây dựng lại as
. Để làm điều đó theo một cách xác định, chúng tôi hy vọng có thể cam kết với một trường hợp duy nhất và làm theo công thức đó. Cụ thể, giả định bs = (Int ': bs2)
và cs = (Int ': cs2)
. Trường hợp nào chúng ta chọn? Có thể là như vậy Int
trong cs
xuất phát từ bs
(và as
là trống). as
Thay vào đó, cũng có thể xuất phát từ (không trống) và điều đó Int
sẽ xuất hiện lại cs
sau này. Chúng ta cần đào sâu hơn cs
để biết và GHC sẽ không làm điều đó.
bs cs -> as
bởi vì chúng ta cần thông tin không phải địa phương vềbs
vàcs
quyết định xemas
nên là khuyết điểm hay không. Chúng ta cần tìm hiểu làm thế nào để thể hiện thông tin này; bối cảnh nào chúng ta sẽ thêm vào một chữ ký loại để đảm bảo nó khi nó không thể được suy luận trực tiếp?