Sto cercando di rappresentare espressioni con famiglie di tipi, ma non riesco a capire come scrivere i vincoli che voglio, e sto iniziando a sentire come se non fosse possibile. Ecco il mio codice:Haskell tipo istanza famiglia con vincoli di tipo
class Evaluable c where
type Return c :: *
evaluate :: c -> Return c
data Negate n = Negate n
instance (Evaluable n, Return n ~ Int) => Evaluable (Negate n) where
type Return (Negate n) = Return n
evaluate (Negate n) = negate (evaluate n)
Il tutto compila bene, ma non esprime esattamente quello che voglio. Nei vincoli dell'istanza Negate
di Evaluable
, dico che il tipo restituito dell'espressione all'interno di Negate
deve essere un Int
(con Return n ~ Int
) in modo che sia possibile chiamare negare su di esso, ma che è troppo restrittivo. Il tipo restituito deve essere solo un'istanza della classe di tipo Num
che ha la funzione negate
. In questo modo Double
s, Integer
s, o qualsiasi altra istanza di Num
potrebbero anche essere negati e non solo Int
s. Ma non posso solo scrivere
Return n ~ Num
, invece, perché Num
è una classe tipo e Return n
è un tipo. Anche non posso mettere
Num (Return n)
invece perché Return n
è un tipo non una variabile di tipo.
È quello che sto cercando di fare anche con Haskell? In caso contrario, dovrebbe essere, o sto fraintendendo qualche teoria dietro di esso? Mi sento come se Java potesse aggiungere un vincolo come questo. Fammi sapere se questa domanda potrebbe essere più chiara.
Modifica: Grazie ragazzi, le risposte stanno aiutando e stanno arrivando a quello che sospettavo. Sembra che il type checker non sia in grado di gestire ciò che mi piacerebbe fare senza UndecidableInstances, quindi la mia domanda è, è ciò che vorrei esprimere davvero indecidibile? È per il compilatore Haskell, ma è in generale? cioè potrebbe esistere un vincolo che significa "verificare che Return n sia un'istanza di Num" che è decidibile per un controllo di tipo più avanzato?
btw, GHC non ha mai consigliato un'estensione di lingua, come ad es. 'FlexibleContexts' o qualcos'altro, durante il processo di prova ed errore? perché sono abbastanza sicuro di averlo fatto - solo una nota a margine sul _ "è anche possibile con Haskell" _ bit. –