Fakta benar yang bagus tentang penggabungan adalah bahwa jika saya tahu ada dua variabel dalam persamaan:
a ++ b = c
Lalu aku tahu yang ketiga.
Saya ingin menangkap ide ini di konser saya sendiri jadi saya menggunakan dependensi fungsional.
{-# 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
Sekarang saya membuat daftar heterogen seperti:
data HList ( as :: [ Type ] ) where
HEmpty :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
Tetapi ketika saya mencoba untuk menyatakan ini karena Concatablesaya memiliki masalah
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)
Saya tidak memenuhi ketergantungan fungsional ketiga saya. Atau lebih tepatnya kompiler percaya kita tidak. Ini karena kompiler percaya bahwa pada instance kedua kita mungkin demikian bs ~ (a ': cs). Dan itu bisa terjadi jika Concatable as (a ': cs) cs.
Bagaimana saya bisa menyesuaikan instance saya sehingga ketiga dependensi puas?
bsdan cs, dan kita ingin mengeksploitasi fundep, yaitu kita ingin merekonstruksi as. Untuk melakukannya dengan cara yang deterministik, kami berharap dapat berkomitmen pada satu instance dan mengikuti resep itu. Konkret, asumsikan bs = (Int ': bs2)dan cs = (Int ': cs2). Contoh mana yang kita pilih? Ada kemungkinan bahwa Intin tersebut csberasal dari bs(dan askosong). Mungkin juga yang berasal dari ( asbukan kosong) sebagai gantinya, dan itu Intakan muncul lagi csnanti. Kita perlu menggali lebih dalam csuntuk mengetahui dan GHC tidak akan melakukan itu.
bs cs -> as, karena kita memerlukan informasi non-lokal tentangbsdancsuntuk memutuskan apakahasharus kontra atau nol. Kita perlu mengetahui bagaimana cara merepresentasikan informasi ini; konteks apa yang akan kita tambahkan ke tanda tangan jenis untuk menjaminnya ketika tidak dapat disimpulkan secara langsung?