Diciamo che ho il seguente codiceHaskell: sicurezza Tipo con logicamente diversi valori booleani
type IsTall = Bool
type IsAlive = Bool
is_short_alive_person is_tall is_alive = (not is_tall) && is_alive
Say, in seguito, ho il seguente
a :: IsAlive
a = False
b :: IsTall
b = True
e chiamare il seguente , ottenendo i due argomenti in modo errato:
is_short_alive_person a b
Questo compilazione riesce con successo, e in fase di esecuzione morti alti sono invece trovati invece di persone corte e vive.
Vorrei che l'esempio precedente non fosse compilato.
Il mio primo tentativo è stato:
newtype IsAlive = IsAlive Bool
newtype IsTall = IsTall Bool
Ma poi non può fare qualcosa di simile.
switch_height :: IsTall -> IsTall
switch_height h = not h
Come not
non è definita su IsTall
s, solo Bool
s.
È possibile estrarre esplicitamente il Bool
s tutto il tempo, ma questo in gran parte vanifica lo scopo.
sostanza, voglio IsTall
s di interagire con altri IsTall
s, proprio come se fossero Bool
s, tranne che non potranno interagire con Bool
s e IsAlive
s senza un cast esplicito.
Qual è il modo migliore per raggiungere questo obiettivo.
p.s. Credo di aver raggiunto questo obiettivo con i numeri facendo in GHC:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype UserID = UserID Int deriving (Eq, Ord, Num)
newtype GroupID = GroupID Int deriving (Eq, Ord, Num)
(cioè UserID e di GroupID di non dovrebbero interagire)
ma io non riesco a farlo con Bool
s (derivante Bool non funziona). Non sono nemmeno sicuro che quanto sopra sia l'approccio migliore comunque.
I tipi 'IsTall' e' IsAlive' desiderati sono una pessima idea. È una falsa generalizzazione dell'idea di solito decente di utilizzare tipi disgiunti per garantire la sicurezza del tipo. Confronta questo con il tuo 'UserID' e' GroupID'; in questo caso ha senso avere tipi separati perché non ha senso passare un ID utente dove è necessario un 'GroupID', o aggiungerne uno all'altro (anche se probabilmente nessuno dei due dovrebbe implementare' Num'). Tuttavia, ha senso verificare se una persona è alta * e * viva, alta * o * viva, * non * alta * e * viva, ecc. –
sacundim: In larga misura ho cambiato idea a questo punto di vista. Ho finito per usare cose come 'newtype Height = Tall | Short' e quindi 'x == Tall' ecc. Un po 'più di digitazione, ma ho pensato che rendesse il codice più leggibile e digitato. – Clinton