Haskell domanda: vincolare i tipi di dati da utilizzare spettacolo
-
13-09-2019 - |
Domanda
Codice:
data Exp a = Const a | Eq (Exp a) (Exp a)
Voglio che il Const a per contenere un valore di tipo mostrano in modo che possa stampare in un secondo momento. Quindi, in C # avrei scritto:
class Const : Exp { IShow X; }
class Eq : Exp { Exp X, Y; }
Come posso fare che in Haskell?
Soluzione
{-# LANGUAGE GADTs #-}
data Exp a where
Const :: Show a => a -> Exp a
Eq :: Exp a -> Exp a -> Exp a
Se si desidera consentire di variare i tipi di dati in diversi rami della Eq
che è troppo fine.
data Exp where
Const :: Show a => a -> Exp
Eq :: Exp -> Exp -> Exp
Altri suggerimenti
Si può fare questo dicendo
data (Show a) => Exp a = Const a | Eq (Exp a) (Exp a)
Ma questo è quasi sempre una cattiva idea perché costringe ogni funzione che utilizza Exp
parlare del vincolo spettacolo, anche se non è mai utilizza i metodi Show
. Invece, mettere il vincolo show su solo le funzioni che è rilevante per. Vedere Real World Haskell per una spiegazione.
Se tutto quello che volete sapere sul argomento per Const
è che si può show
, perché non solo memorizzare il valore String
conseguente costruttore, invece? Ad esempio:
data Exp = Const String | Eq Exp Expr
example = Eq (Const (show 0)) (Const (show ""))
Questa assomiglia da vicino la versione C #.
Per rispondere alla seconda domanda, ha chiesto nei commenti, Eq (Const 0) (Const "")
non è ottenibile con il tipo di dati si hanno a causa Exp Integer
e Exp String
non sono dello stesso tipo. Una possibilità è quella di fare qualcosa di simile
data Exp = forall a . Show a => Const a | Eq Exp Exp
Sia che non vi farà alcun bene dipende da cosa hai intenzione di fare con il tipo.
Edit: Questo richiede estensioni del linguaggio sia abilitato come detto
.Vorrei solo dichiarare il vostro tipo di dati un'istanza del tipo di classe Mostra:
data Exp a = Const a | Eq (Exp a) (Exp a)
instance (Show a) => Show (Exp a) where
show (Const a) = show a
show (Eq x y ) = "[ " ++ show x ++ " , " ++ show y ++ " ]"
Guardate cosa succede quando si carica questo ghci e fare:
*Main> let x = Eq (Const 1) (Eq (Const 2) (Const 3))
*Main> x
[1 , [2 , 3] ]
Commento Rispondere:
Si può facilmente fare con diversi tipi. Si supponga di voler analizzare le espressioni matematiche. Si può avere la seguente struttura, ad esempio:
data Expr = Var String | Sum (Expr) (Expr) | Number Int | Prod (Expr) (Expr)
Questo è sufficiente per rappresentare qualsiasi espressione fatta di somme e prodotti di numeri e variabili denominate. Ad esempio:
x = Sum (Var "x") (Prod (Number 5) (Var "y"))
rappresenta: x + 5y
Per stampare questo bellissimo farei:
instance Show Expr where
show (Var s) = show s
show (Sum x y) = (show x) ++ " + " (show y)
show (Prod x y) = (Show x) ++ (show y)
show (Number x) = show x
Questo farebbe il trucco. Si potrebbe anche usare GADTs:
data Expr where
Var :: String -> Expr
Sum :: Expr -> Expr -> Expr
ecc ... e poi istanziare questo come Show.