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 Concatable
saya 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?
bs
dan 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 Int
in tersebut cs
berasal dari bs
(dan as
kosong). Mungkin juga yang berasal dari ( as
bukan kosong) sebagai gantinya, dan itu Int
akan muncul lagi cs
nanti. Kita perlu menggali lebih dalam cs
untuk mengetahui dan GHC tidak akan melakukan itu.
bs cs -> as
, karena kita memerlukan informasi non-lokal tentangbs
dancs
untuk memutuskan apakahas
harus 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?