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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top