Question

Code:

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

Je veux que le Const a pour contenir une valeur de type émission afin que je puisse l'imprimer ultérieurement. Donc, en C # je voudrais écrire:

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

Comment puis-je faire dans Haskell?

Était-ce utile?

La solution

{-# LANGUAGE GADTs #-}

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

Si vous souhaitez autoriser pour différents types de données dans les différentes branches de Eq qui est très bien aussi.

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

Autres conseils

Vous pouvez le faire en disant

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

Mais ce qui est presque toujours une mauvaise idée, car elle oblige toutes les fonctions qui utilise Exp mentionner la contrainte de spectacle, même si elle utilise jamais les méthodes de Show. Au lieu de cela, mettre la contrainte de spectacle uniquement sur les fonctions qu'il est pertinent pour. Voir Real World Haskell pour une explication.

Si tout ce que vous voulez savoir sur l'argument de Const est que vous pouvez show, pourquoi ne pas simplement stocker la valeur String résultant du constructeur à la place? Par exemple:

data Exp = Const String | Eq Exp Expr

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

Cette version ressemble étroitement C #.

Pour répondre à la deuxième question, posée dans les commentaires, Eq (Const 0) (Const "") n'est pas réalisable avec le type de données que vous avez parce Exp Integer et Exp String ne sont pas du même type. Une option est de faire quelque chose comme

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

Que cela vous faire du bien dépend de ce que vous avez l'intention de faire avec le type.

Edit: Cela nécessite des extensions de langage être activé comme mentionné

.

Je voudrais juste déclarer votre datatype une instance de la classe de type 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 ++ " ]"

Regardez ce qui se passe lorsque vous chargez ceci dans ghci et faites:

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

Répondre à un commentaire:

Vous pouvez facilement faire face à différents types. Supposons que vous voulez analyser des expressions mathématiques. Vous pouvez avoir la structure suivante, par exemple:

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

Il suffit de représenter toute expression faite des sommes et des produits de nombres et variables nommées. Par exemple:

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

représente: x + 5y

Pour imprimer ce magnifique que je ferais:

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

Ce serait faire l'affaire. Vous pouvez également utiliser GADTs:

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

etc ... puis instancier ce qu'Afficher.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top