Frage

Code:

data Exp a = Const a | Eq (Exp a) (Exp a)

Ich möchte, dass die Const a einen Wert vom Typ Show enthalten, so dass ich es später drucken können. Also in C # würde ich schreiben:

class Const : Exp { IShow X; }
class Eq : Exp { Exp X, Y; }

Wie kann ich das tun in Haskell?

War es hilfreich?

Lösung

{-# LANGUAGE GADTs #-}

data Exp a where
    Const :: Show a => a -> Exp a
    Eq :: Exp a -> Exp a -> Exp a

Wenn Sie für verschiedene Datentypen in verschiedenen Zweigen des Eq zulassen will, dass auch in Ordnung ist.

data Exp where
    Const :: Show a => a -> Exp
    Eq :: Exp -> Exp -> Exp

Andere Tipps

Sie können dies tun, indem er sagte

data (Show a) => Exp a = Const a | Eq (Exp a) (Exp a)

Aber das ist fast immer eine schlechte Idee, weil es jede Funktion, die Exp verwendet zwingt die Show-Einschränkung zu erwähnen, auch wenn es nie die Show Methoden verwendet. Stattdessen setzen die Show-Einschränkung auf nur die Funktionen für sie relevant ist. Siehe Real World Haskell für eine Erklärung.

Wenn alles, was Sie über das Argument wissen wollen, ist zu Const, dass Sie es show können, warum speichert nicht nur den resultierenden String Wert im Konstruktor statt? Zum Beispiel:

data Exp = Const String | Eq Exp Expr

example = Eq (Const (show 0)) (Const (show ""))

Dies ähnelt C # Version.

die zweite Frage zu beantworten, in den Kommentaren gefragt ist Eq (Const 0) (Const "") nicht erreichbar mit dem Datentyp Sie haben, weil Exp Integer und Exp String ist nicht vom gleichen Typ. Eine Möglichkeit ist, etwas zu tun, wie

data Exp = forall a . Show a => Const a | Eq Exp Exp

Ob das Sie tun etwas Gutes hängt davon ab, was Sie vorhaben, mit der Art auf zu tun.

Edit: Das tut Spracherweiterungen erfordern aktiviert sein, wie erwähnt

.

Ich möchte nur erklären, um Ihren Datentyp eine Instanz der Typklasse Show:

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 ++ " ]"

Sehen Sie, was passiert, wenn man diese in GHCI laden und zu tun:

*Main> let x = Eq (Const 1) (Eq (Const 2) (Const 3))
*Main> x      
[1 , [2 , 3] ]

Die Beantwortung Kommentar:

Sie können ganz einfach mit verschiedenen Arten umgehen. Angenommen, Sie mathematische Ausdrücke analysieren möchten. Sie können die folgende Struktur haben, zum Beispiel:

data Expr  = Var String | Sum (Expr) (Expr) | Number Int | Prod (Expr) (Expr)

Das ist genug, um jeden Ausdruck von Summen und Produkten von Zahlen und benannten Variablen gemacht darzustellen. Zum Beispiel:

x = Sum (Var "x") (Prod (Number 5) (Var "y")) 

steht: x + 5j

Um dies zu drucken schön ich tun würde:

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

Dies würde den Trick tun. Sie könnten auch GADTs verwenden:

 data Expr where
      Var :: String -> Expr
      Sum :: Expr -> Expr -> Expr

etc ... und dann instanziiert dies als Show.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top