在 Haskell 中实现一种语言:同构列表
Implementing a language in Haskell: homogenous lists
我正在尝试为 haskell 中的函数式语言创建解释器(我是该语言的新手)。我正在创建可能是极简主义和便利性的奇怪组合——没有抽象数据类型,但我想提供制作同类列表的能力。
所以我的基本变量是 data Datum = DatInt Int | DatDbl Double | DatBool Bool
并且我意识到我完全不确定如何表示同类列表。添加一个构造函数 List Datum
或类似的东西会产生一个异构列表,并为每种类型创建一个单独的列表,即 ListInt [Int] | ListDbl [Double]
会排除列表列表。
表示同类列表的最佳方式是什么?
一个有用的概念(无论您是否想要性感类型)是类型标签。非性感版好对付很多
data Tag = IntTag
| DoubleTag
| BoolTag
| ListTag Tag
deriving (Eq, Show)
现在您的类型由这些不同的标签表示。 Int
由 IntTag
表示。 Int
的列表由 ListTag IntTag
.
表示
现在您可以像这样表示带类型注释的表达式:
data Expr = IntLit Int
| DoubleLit Double
| BoolLit Bool
| ListLit Tag [Expr]
-- Check that an expression is validly annotated
typeCheck :: Expr -> Maybe Tag
typeCheck IntLit{} = Just IntTag
...
typeCheck (ListLit tag els)
| all good els = Just (ListTag tag)
| otherwise = Nothing
where
good el = case typeCheck el of
Nothing -> False
Just res = res == tag
我正在尝试为 haskell 中的函数式语言创建解释器(我是该语言的新手)。我正在创建可能是极简主义和便利性的奇怪组合——没有抽象数据类型,但我想提供制作同类列表的能力。
所以我的基本变量是 data Datum = DatInt Int | DatDbl Double | DatBool Bool
并且我意识到我完全不确定如何表示同类列表。添加一个构造函数 List Datum
或类似的东西会产生一个异构列表,并为每种类型创建一个单独的列表,即 ListInt [Int] | ListDbl [Double]
会排除列表列表。
表示同类列表的最佳方式是什么?
一个有用的概念(无论您是否想要性感类型)是类型标签。非性感版好对付很多
data Tag = IntTag
| DoubleTag
| BoolTag
| ListTag Tag
deriving (Eq, Show)
现在您的类型由这些不同的标签表示。 Int
由 IntTag
表示。 Int
的列表由 ListTag IntTag
.
现在您可以像这样表示带类型注释的表达式:
data Expr = IntLit Int
| DoubleLit Double
| BoolLit Bool
| ListLit Tag [Expr]
-- Check that an expression is validly annotated
typeCheck :: Expr -> Maybe Tag
typeCheck IntLit{} = Just IntTag
...
typeCheck (ListLit tag els)
| all good els = Just (ListTag tag)
| otherwise = Nothing
where
good el = case typeCheck el of
Nothing -> False
Just res = res == tag