Ho un problema relativo al sistema di tipo Haskell. Questa non è la prima volta che ho riscontrato i limiti del sistema di tipi. Ometterò i dettagli del mio progetto e utilizzerò un esempio semplificato. Ecco il codice:Haskell: le variabili di tipo possono essere utilizzate all'interno della definizione della funzione?
-- Works
foo :: (Bounded a, Enum a) => a
foo = minBound
-- "ambiguous" constraint:
-- 'a' has no occurrences in type declaration
bar :: (Bounded a, Enum a) => Int
bar = fromEnum minBound
-- Too much information in return
-- but I can show haskell the appropriate type of 'min'
baz :: (Bounded a, Enum a) => (a, Int)
baz = let min = minBound
in (min, someFunction . fromEnum $ min)
-- Type constraint 'a' not ambiguous
-- (or at least that isn't the compiler error message)
-- but Haskell doesn't know which 'minBound' to use
barrer :: (Bounded a, Enum a) => a
barrer = let min = minBound -- <- min's type is ambiguous
in toEnum . someFunction . fromEnum $ min
Quello che sto cercando di realizzare è simile a barrer
: In primo luogo, utilizzare il valore minBound
specifiche per il tipo a
e 'cast' in un numero intero. Nel mio progetto, procedo a trasformare questo numero intero (per evitare gli overflow aritmetici intermedi quando si utilizza il tipo a
) e "lanciarli" per digitare a
(dopo un po 'di magia mod
). Come posso dire ad Haskell il tipo appropriato di minBound
? È possibile?
La soluzione ovvia è aggiungere un'annotazione di minBound :: a
. Questo avrebbe anche risolto bar
. Il problema: la variabile di tipo a
sembra essere fuori ambito nella definizione della funzione, poiché Haskell rinfresca minBound :: a
in minBound a0
nel messaggio di errore. C'è un modo per fare questo tipo di annotazione?
Una cattiva modifica che ho usato era di limitare il tipo della chiamata minBound
includendola nel tipo di ritorno della funzione, a la baz
. Questa soluzione non è l'ideale. Qualcuno ha qualche consiglio?
"Variabili di tipo scoped" - Esattamente quello che volevo. E detto molto più succintamente del mio titolo! – bimmo
Come lo faresti anche con asTypeOf e undefined? Mi sembra che non si possa mai ottenere un valore di tipo 'a' da puntare a TypeTypeOf, perché nessuno viene passato o restituito da questa funzione. Si può ottenere solo uno tramite variabili di tipo scoped, a quel punto non è più necessario asTypeOf o undefined. – amalloy
@amalloy Poiché 'asTypeOf' non valuta mai il suo secondo argomento, lo usa solo per l'inferenza di tipo, puoi legarlo in nodi come questo:' 'barrer = let min = minBound' asTypeOf' result; risultato = toEnum. qualche funzione. daEnum $ min in result'' –