هاسكل السؤال:تقييد أنواع البيانات لاستخدام تظهر
-
13-09-2019 - |
سؤال
كود:
data Exp a = Const a | Eq (Exp a) (Exp a)
أريد Const a أن تحتوي على قيمة من نوع المعرض بحيث يمكن طباعتها في وقت لاحق.حتى في C# أود أن أكتب:
class Const : Exp { IShow X; }
class Eq : Exp { Exp X, Y; }
كيف يمكن أن أفعل ذلك في هاسكل ؟
المحلول
{-# 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 Integer
و Exp String
ليسوا نفس النوع. خيار واحد هو القيام بشيء مثل
data Exp = forall a . Show a => Const a | Eq Exp Exp
سواء كان ذلك سيفعلك جيدا يعتمد على ما تخطط للقيام بهذه النوع.
تحرير: هذا يتطلب تمكين ملحقات اللغة كما هو مذكور.
أود أن أعلن فقط Datatype مثيل عرض فئة النوع:
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
إلخ ... ثم إنشاء هذا كما عرض.