代码:

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

我想要的 CONST一个包含的节目类型的值,这样我可以稍后打印。因此,在C#我会写:

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

我如何能做到这一点在Haskell?

有帮助吗?

解决方案

{-# LANGUAGE GADTs #-}

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

如果你想允许在Eq那也没关系的不同分支的不同的数据类型。

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

其他提示

您可以这样做。

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

但是,这是几乎总是一个坏主意,因为它会强制使用Exp提秀约束,即使从来没有使用Show方法每一个功能。相反,把展会的约束上只是它的相关的职能。请参见真实世界哈斯克尔一个解释。

如果你想知道即将Const的说法是,你可以show它,为什么不直接存储在构造函数,而不是导致String价值?例如:

data Exp = Const String | Eq Exp Expr

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

这非常类似于你的C#版本。

要回答第二个问题,在评论中问道,Eq (Const 0) (Const "")是不是和你有数据类型实现的,因为Exp IntegerExp String是不是同一类型。一种选择是像做

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

至于这是否会做你任何好处取决于你打算使用的类型做什么。

编辑:这确实需要语言扩展如所提到的,以使能

我只想宣布你的数据类型的类型类展会的一个实例:

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

看看会发生什么,当你加载这个在ghci中做:

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

<强>应答的评论:

您可以轻松应对不同的类型。假设你想分析的数学表达式。可以具有以下结构,例如:

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

这是足以表示由求和和数字与命名变量的产品的任何表达。例如:

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

表示:X + 5Y

要打印本精美的我会做:

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

这会做的伎俩。你也可以使用GADTs:

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

等...然后实例此作为显示。

scroll top