Pregunta

Código:

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

Quiero que el Const a para contener un valor de tipo de presentación para que pueda imprimir más tarde. Así que en C # que iba a escribir:

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

¿Cómo puedo hacer que en Haskell?

¿Fue útil?

Solución

{-# LANGUAGE GADTs #-}

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

Si desea permitir la variación de los tipos de datos en diferentes ramas de Eq eso también está bien.

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

Otros consejos

Usted puede hacer esto diciendo

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

Pero esto es casi siempre una mala idea ya que obliga a todas las funciones que utiliza Exp mencionar el programa de restricción, aunque nunca utiliza los métodos Show. En su lugar, poner el programa de restricción en tan sólo las funciones que es relevante para. Ver Real World Haskell una explicación.

Si todo lo que quiere saber sobre el argumento de Const es que se puede show que, ¿por qué no almacenar el valor resultante String en el constructor en su lugar? Por ejemplo:

data Exp = Const String | Eq Exp Expr

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

Esto se parece mucho a su versión C #.

Para responder a la segunda pregunta, hecha en los comentarios, Eq (Const 0) (Const "") no es alcanzable con el tipo de datos que tiene, ya Exp Integer y Exp String no son del mismo tipo. Una opción es hacer algo como

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

Ya sea que no le hará ningún bien depende de lo que estés pensando en hacer con el tipo.

Edit: Esto requiere extensiones de lenguaje para ser habilitado como se mencionó

.

Me acaba de declarar el tipo de datos de una instancia de la clase Mostrar tipo:

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

Mira lo que ocurre cuando se carga en este ghci y hacer:

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

Responder a un comentario:

Puede ocuparse fácilmente de diferentes tipos. Supongamos que se desea analizar expresiones matemáticas. Usted puede tener la siguiente estructura, por ejemplo:

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

Esto es suficiente para representar cualquier expresión hecha de sumas y productos de números y variables con nombre. Por ejemplo:

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

representa: x + 5y

Para imprimir esta muy bien que lo haría:

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

Esto haría el truco. También es posible usar GADTs:

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

etc ... y luego una instancia esto como Mostrar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top