Se avete bisogno di un contesto, il modo più semplice sarebbe quella di noi e una dichiarazione data
:
data (Integral a) => IntegralData a = ID [a]
type ListOfIntegralData a = [IntegralData a]
*Main> :t [ ID [1234,1234]]
[ID [1234,1234]] :: Integral a => [IntegralData a]
Questo ha il (sola) effetto di rendere sicuro un Integral
contesto viene aggiunto ad ogni funzione che utilizza il tipo di dati IntegralData
.
sumID :: Integral a => IntegralData a -> a
sumID (ID xs) = sum xs
La ragione principale sinonimo type
non funziona per voi è che tipo di sinonimi sono concepiti come solo che - qualcosa che sostituisce una tipo, non un tipo di firma .
Ma se si vuole andare esistenziale il modo migliore è con un GADT, perché gestisce tutti i problemi di quantificazione per voi:
{-# LANGUAGE GADTs #-}
data IntegralGADT where
IG :: Integral a => [a] -> IntegralGADT
type ListOfIG = [ IntegralGADT ]
Poiché si tratta essenzialmente di tipo esistenziale, potete mescolarli in su:
*Main> :t [IG [1,1,1::Int], IG [234,234::Integer]]
[IG [1,1,1::Int],IG [234,234::Integer]] :: [ IntegralGADT ]
Che potresti trovare abbastanza comodo, a seconda dell'applicazione.
Il vantaggio principale di un GADT su una dichiarazione di dati è che quando si pattern match, è implicitamente ottiene il Integral
contesto:
showPointZero :: IntegralGADT -> String
showPointZero (IG xs) = show $ (map fromIntegral xs :: [Double])
*Main> showPointZero (IG [1,2,3])
"[1.0,2.0,3.0]"
Ma la quantificazione esistenziale è talvolta usato per le ragioni sbagliate, (ad esempio, volendo per mescolare tutti i tuoi dati in una lista perché è quello che ti serve da da lingue digitate dinamicamente, e non ti sei abituato alla tipizzazione statica e ai suoi vantaggi ancora).
Qui credo che sia più problemi che ne vale la pena, a meno che non necessità di mescolare diversi tipi Integral insieme senza convertirli. Non vedo un motivo perché questo sarebbe d'aiuto, perché dovrai convertirli quando li usi.
Ad esempio, non è possibile definire
unIG (IG xs) = xs
perché non ha nemmeno il tipo di controllo. Regola generale: non puoi fare cose che menzionano il tipo a
sul lato destro.
Tuttavia, questo è OK perché abbiamo convertire il tipo di a
:
unIG :: Num b => IntegralGADT -> [b]
unIG (IG xs) = map fromIntegral xs
quantificazione Qui esistenziale ha costretto a convertire i dati quando penso che il tuo piano originale era quello di non dover! Puoi convertire tutto in numero intero invece di questo.
Se vuoi le cose semplici, mantienile semplici. La dichiarazione dei dati è il modo più semplice per assicurarti di non inserire dati nel tuo tipo di dati, a meno che non sia già membro di una classe di tipi.
Anche 'ListOfAsdf2' richiede un parametro di tipo. 'tipo ListOfAsdf2 a = Integrale a => [Asdf2 a]'. –
Ho provato anche quello, ma ho ottenuto lo stesso errore .. = ( – dak
Sì, hai bisogno di 'ImpredicativeTypes', come diceva il compilatore, ma in realtà, non hai bisogno del parametro type quindi. –