Haskellの質問:ショーを使用するデータ型を制約します
-
13-09-2019 - |
質問
コード:
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
を使用するすべての機能を強制するため、これはほとんど常に悪い考えです。代わりに、それはのための関連ちょうど機能にショーの制約を置きます。 実世界Haskellのを参照してください。 A>説明のために。
あなたはConst
の引数について知りたいすべてがあなたがそれをshow
できるということであれば、なぜだけではなく、コンストラクタでの結果のString
値を格納していませんか?たとえばます:
data Exp = Const String | Eq Exp Expr
example = Eq (Const (show 0)) (Const (show ""))
これは、密接にあなたのC#バージョンに似ています。
Eq (Const 0) (Const "")
とExp Integer
が同じタイプではありませんので、コメントで尋ねた2つ目の質問に答えるために、Exp String
は、あなたが持っているデータ型で達成可能ではありません。 1つのオプションは、のような何かを行うことです。
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
など...そしてショーとしてこれをインスタンス化します。