我有困難的時候,說服GHC該列表操作的某些屬性 是真實的。之前我提供了我 工作的代碼,我給我感興趣的屬性的一個簡單的例子 假設我們有一些類型級列表xs
:劈裂GHC
xs ~ '[ 'A, 'B, 'C, 'D, 'E, 'F ]
我們降一些元素,並採取 元素的同一個號碼:
Drop 2 xs ~ '[ 'C, 'D, 'E, 'F ]
TakeReverse 2 xs ~ '[ 'B, 'A ]
這應該是顯而易見的是,如果我使用的2後繼申請Drop
和TakeReverse
,然後我就可以爆開的的 Drop 2 xs
,並把它的頂部TakeReverse 2 xs
:
Drop 3 xs ~ '[ 'D, 'E, 'F ]
TakeReverse 3 xs ~ '[ 'C, 'B, 'A ]
下面的代碼中有一個名爲moveRight
函數試圖 使用這個屬性。我已經將我的實際代碼縮減爲一個有點小的例子, 說明了這個問題並且沒有依賴關係。
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE UndecidableInstances #-}
module Minimal where
import Data.Type.Equality
data Nat = Z | S Nat
data Natty (n :: Nat) where
Zy :: Natty 'Z
Sy :: Natty n -> Natty ('S n)
data HRec (vs :: [*]) where
HRecNil :: HRec '[]
HRecCons :: x -> HRec xs -> HRec (x ': xs)
data HProxy (vs :: [k]) where
HProxyNil :: HProxy '[]
HProxyCons :: HProxy xs -> HProxy (x ': xs)
data Parts n rs = Parts
{ partLeft :: HRec (Drop n rs)
, partRight :: HRec (TakeReverse n rs)
, partNatty :: Natty n
, partProxy :: HProxy rs
}
-- The type families Drop, Take, and TakeReverse
-- are all partial.
type family Drop (n :: Nat) (xs :: [k]) :: [k] where
Drop 'Z xs = xs
Drop ('S n) (x ': xs) = Drop n xs
type family Take (n :: Nat) (xs :: [k]) :: [k] where
Take 'Z xs = '[]
Take ('S n) (x ': xs) = x ': Take n xs
type family TakeReverse (n :: Nat) (xs :: [k]) :: [k] where
TakeReverse n xs = TakeReverseHelper '[] n xs
type family TakeReverseHelper (ys :: [k]) (n :: Nat) (xs :: [k]) :: [k] where
TakeReverseHelper res 'Z xs = res
TakeReverseHelper res ('S n) (x ': xs) = TakeReverseHelper (x ': res) n xs
moveRight :: Parts n rs -> Parts (S n) rs
moveRight (Parts [email protected](HRecCons pleftHead _) pright natty proxy) =
case dropOneProof natty proxy of
Refl -> Parts (dropOne pleft) (HRecCons pleftHead pright) (Sy natty) proxy
dropOneProof :: Natty n -> HProxy rs -> (Drop ('S n) rs :~: Drop ('S 'Z) (Drop n rs))
dropOneProof Zy _ = Refl
dropOneProof (Sy n) (HProxyCons rs) = case dropOneProof n rs of
Refl -> Refl
dropOne :: HRec rs -> HRec (Drop ('S 'Z) rs)
dropOne (HRecCons _ rs) = rs
此代碼不會因爲moveRight
編譯。基本上,我能 證明,從左邊下降一個額外的元素給它 正確的類型,但我不能表明,添加這個元素向右 側使其具有正確的類型。
我真的很樂意接受任何改變。我可以改變類型系列, 引入額外的證人等,只要moveRight
變成 可能寫。
如果我需要進一步澄清什麼,我試圖做的,請讓我知道。謝謝。
@dfeuer你是對的。我改變了它。 –
對你來說澄清是有幫助的,是的。我懷疑你需要以不同的方式使用類型族。我懷疑這可能有助於通過使用長度索引的異構列表並將它們與「Fin」值分開來「預熱」。 – dfeuer