You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中如何泛化GADT的Value类型,简化实例实现?

问题:Haskell中为带类型的Value GADT实现通用构造器与类型类实例

我正在实现一个函数式语言的解释器,需要做运行时类型检查,因为输入语言里不同表达式会返回不同类型的值。

最初定义的基础装箱数据类型如下:

-- 扩展值类型
data Value 
  = StringValue T.Text 
  | IntValue Integer
  | BoolValue Bool
  | Error EvalError
  deriving (Eq, Show)

这些值会在解析树表达式求值后返回,表达式的定义类似这样:

data Expression = Constant Value a |
                  UnaryOp (Value a -> Value b) Expression |
                  BinaryOp (Value a -> Value b  -> Value c) Expression Expression

为定义操作,我写了一个辅助函数:

lift :: (Int -> Int -> Int) -> Value -> Value -> Value
lift f (IntValue x) (IntValue y) = IntValue $ f x y
lift _ _ _ = Error TypeError

这个函数可以用来构建运算符,示例如下:

case op of
  '+' -> (BinaryOp (lift (+)) arg1 arg2, rest2)
-- 其他运算符类似

后续实现越来越繁琐,我觉得在Haskell已有对应类型类的情况下,自己写lift方法和相关运算符有点多余。我曾尝试把Value做成Functor和Applicative的实例,但原来的Value没有类型变量,没法实现。后来了解到GADT,就把Value类型改成了这样:

data Value a where
  StringValue :: T.Text    -> Value T.Text
  IntValue    :: Int       -> Value Int
  BoolValue   :: Bool      -> Value Bool
  Error       :: EvalError -> Value EvalError

现在我尝试为它实现Functor和Applicative实例。最初的Functor实例是这样的:

instance Functor Value where
  fmap f (StringValue t) = StringValue $ f t
  fmap f (IntValue x)    = IntValue $ f x
  fmap f (BoolValue b)   = BoolValue $ f b
  fmap _ _               = Error TypeError

我觉得这些重复的fmap分支太冗余了,要是以后要处理int转string这类类型转换,维护起来会特别麻烦。于是我试着用Applicative和辅助函数来规避,现在的实现变成了这样:

instance Functor Value where
  fmap f v = pure $ f (extractValue v)

extractValue :: Value a -> a
extractValue (StringValue t) = t
extractValue (IntValue n) = n
extractValue (BoolValue b) = b
extractValue (Error e) = e

但这种重复的拆箱代码同样冗余,而且pure的实现也需要大量反向的重复代码。如果把Value改成通用构造器,之后又没法对值类型做模式匹配,会导致类似加法实现的问题——编译器没法确认值类型确实是int。

我希望能通过通用构造器来做模式匹配,比如像下面这样:

extractValue :: Value a -> a
extractValue (T t) = t

instance Applicative Value where
  pure x = T x
-- 其他实例方法类似

想问下Haskell里有没有这样的实现方式?


内容的提问来源于stack exchange,提问作者Joel Croteau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:05:03