Come si ottiene e si utilizza il tipo dipendente da una classe di caratteri con dipendenze funzionali?Come si ottiene e si utilizza il tipo dipendente da una classe di caratteri con dipendenze funzionali?
Per chiarire e dare un esempio del mio ultimo tentativo (minimizzati da codice vero e stavo scrivendo):
class Identifiable a b | a -> b where -- if you know a, you know b
idOf :: a -> b
instance Identifiable Int Int where
idOf a = a
f :: Identifiable Int b => Int -> [b] -- Does ghc infer b from the functional dependency used in Identifiable, and the instance?
f a = [5 :: Int]
Ma ghc non implica B, a quanto pare, come esso stampa questo errore:
Couldn't match expected type ‘b’ with actual type ‘Int’
‘b’ is a rigid type variable bound by
the type signature for f :: Identifiable Int b => Int -> [b]
at src/main.hs:57:6
Relevant bindings include
f :: Int -> [b] (bound at src/main.hs:58:1)
In the expression: 5 :: Int
In the expression: [5 :: Int]
In an equation for ‘f’: f a = [5 :: Int]
per il contesto, ecco un esempio meno minimizzato:
data Graph a where
Graph :: (Identifiable a b) => GraphImpl b -> Graph a
getImpl :: Identifiable a b => Graph a -> GraphImpl b
getImpl (Graph impl) = impl
La soluzione qui sarebbe da aggiungere b come tipo arg a Graph:
data Graph a b | a -> b where
Graph :: (Identifiable a b) => GraphImpl b -> Graph a
Il contesto completo: Ho una Graph
di soggetti che hanno ciascuno un id, ogni entità è assegnato al nodo 1. Puoi cercare un nodo per entità. Ho anche un Graph'
che consiste di nodi (a cui è possibile assegnare un'entità) e per cercare un nodo è necessario fornire l'id del nodo, che è un Int. Graph
utilizza Graph'
internamente. Ho uno IdMap
che associa gli ID delle entità agli ID dei nodi in Graph'
. Questo è il mio Graph
definizione:
data Graph a where
Graph :: (Identifiable a b) => {
_idMap :: IdMap b,
_nextVertexId :: Int,
_graph :: Graph' a
} -> Graph a
Risposta: Usare le famiglie tipo, vedere Daniel Wagner's answer. Per la storia completa, vedi Reid Barton's answer.
@Carsten Grazie, 'idOf' davvero funzionato. Per quanto riguarda il vincolo, stavo cercando di vedere se c'era una funzionalità in haskell per "abbinare pattern" ad un tipo con una classe. Per il secondo esempio, c'è un modo per farlo funzionare senza usare 'Graph a b | a -> b', e/o c'è una ragione dal punto di vista del design per fare comunque quest'ultimo? – timdiels