Per prima cosa, ho iniziato con alcuni tipi di numeri naturali tipici di tipo livello.Sono possibili prove di istanze familiari di tipo?
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
data Nat = Z | S Nat
type family Plus (n :: Nat) (m :: Nat) :: Nat
type instance Plus Z m = m
type instance Plus (S n) m = S (Plus n m)
Quindi volevo creare un tipo di dati che rappresentasse una griglia n-dimensionale. (Una generalizzazione di ciò che si trova al Evaluating cellular automata is comonadic.)
data U (n :: Nat) x where
Point :: x -> U Z x
Dimension :: [U n x] -> U n x -> [U n x] -> U (S n) x
L'idea è che il tipo U num x
è il tipo di un num
griglia dimensionale di x
s, che è "concentrato" su un punto della griglia .
così ho voluto rendere questo un comonad, e ho notato che c'è questa funzione potenzialmente utile che posso fare:
ufold :: (x -> U m r) -> U n x -> U (Plus n m) r
ufold f (Point x) = f x
ufold f (Dimension ls mid rs) =
Dimension (map (ufold f) ls) (ufold f mid) (map (ufold f) rs)
possiamo ora implementare una "dimensione join" che trasforma una griglia n-dimensionale griglie m-dimensionali in una griglia dimensionale (n + m), in termini di questo combinatore. Questo sarà utile quando si ha a che fare con il risultato di cojoin
che produrrà griglie di griglie.
dimJoin :: U n (U m x) -> U (Plus n m) x
dimJoin = ufold id
Fin qui tutto bene. Ho anche notato che l'istanza Functor
può essere scritta in termini di ufold
.
instance Functor (U n) where
fmap f = ufold (\x -> Point (f x))
Tuttavia, ciò provoca un errore di tipo.
Couldn't match type `n' with `Plus n 'Z'
Ma se improvvisare qualche pasta copia, quindi l'errore di tipo va via.
instance Functor (U n) where
fmap f (Point x) = Point (f x)
fmap f (Dimension ls mid rs) =
Dimension (map (fmap f) ls) (fmap f mid) (map (fmap f) rs)
Beh, odio il sapore della pasta, quindi la mia domanda è questa. Come posso dire al sistema di tipi che Plus n Z
è uguale a n
? E il problema è questo: non è possibile modificare le istanze di tipo family che potrebbero causare dimJoin
per produrre un errore di tipo simile.
L'inserimento di 'Plus n Z ~ n' nel contesto dell'istanza di' Functor'? Hai solo bisogno di replicare quel vincolo finché 'n' diventa monomorfico. –