creare una classe tipo che accetta il tipo di prodotti naturali a livello Z, (SZ), (S (SZ)) ... ecc, si può semplicemente dichiarare le istanze in modo ricorsivo in quanto tale:Istanze basate su predicato a livello di livello?
data Z
data S a
class Type a
instance Type Z
instance Type (S a)
E ' possibile creare un'istanza di classe tipo basata su predicati a livello di tipo? Per esempio, io voglio essere in grado di dire:
{-# LANGUAGE MultiParamTypeClasses #-}
class Type a b
instance Type x y when (x :+: y == 8)
Dove :+:
è digitare aggiunta di livello, e ==
è di tipo a livello di uguaglianza da Data.Type.Equality
, in modo che le istanze vengono create solo per coppie di NAT che aggiungono fino a 8
La notazione è simile a questa disponibile in Haskell? Altrimenti, come si compirebbe qualcosa del genere?
Edit: Questo post è stato ispirato by the Haskell wiki article on smart constructors, dove una classe di tipo InBounds
è stato dichiarato per verificare staticamente che l'argomento di tipo phantom passato a un costruttore intelligente fosse in qualche gamma di Nat
s, il costruttore intelligente era:
resistor :: InBounds size => size -> Resistor size
resistor _ = Resistor
Cercando di fare qualcosa di simile nel mio esempio (dopo aver usato la risposta di leftaroundabout) mi dà un errore:
construct :: (Type a b) => a -> b -> MyType a b
construct _ _ = MyType
>>> Expected a type, but a has kind Nat…
l'esempio dal wiki Haskell funziona perché doesn' t utilizzare DataKinds, è possibile passare un tipo di tipo Nat
a una funzione a livello di valore?
Grazie per aver risposto, ma questo non ha funzionato esattamente per quello che stavo cercando di fare, quindi ho aggiornato la mia domanda per includere più contesto. –
Questo esempio sul Wiki utilizza i tipi di fantasma in modo inutile: non è necessario alcun argomento per 'resistore', basta renderlo' resistor :: InBounds size => Resistor size', 'resistor = Resistor'. Se hai bisogno di racchiudere un valore di tipo data in un argomento, usa ['Tagged'] (http://hackage.haskell.org/package/tagged) (di cui non sono un grande fan, ma a volte è giusto). – leftaroundabout
Cambiare il mio codice in 'construct :: (Type a b) => MyType a b' ,' construct = MyType' continua a dare lo stesso errore. –