我正在尝试创建以下数据类型:
data ExprValues = ExprNum Int |
ExprIdent String |
ExprChar Char |
ExprString String
deriving(Eq, Show, Read)
data ExprOverall = ExprFunCall ExprValues --correct this to use ExprIdent solely
deriving(Eq, Show, Read)
但是,正如评论中所示,我希望 ExprFuncall 旁边的 ExprValues 仅接受 ExprIdent String,而不是其他 ExprValues。我怎样才能做到这一点?
最佳答案
首先,如果您只想允许构造函数,为什么不直接“内联”它 - 将 String
存储在 ExprOverall
中并完成?
但更一般地说,这种限制可以通过 GADT 来实现。通常,尤其是对于此类类似 AST 的类型,您希望表达表达式所代表的整体类型。在那里,ExprIdent
可能是多态的,而其他的是具体的:
{-# LANGUAGE GADTs #-}
data ExprValues a where
ExprNum :: Int -> ExprValues Int
ExprIdent :: String -> ExprValues a
ExprChar :: Char -> ExprValues Char
ExprString :: String -> ExprValues String
然后,为了在 ExprOverall
中使用,您选择一个仅适用于 ExprIdent
构造函数的唯一标记类型(因为它允许任何类型变量 a
,而其他则特定于具体类型)。
data FreeIdentifier
data ExprOverall = ExprFunCall (ExprValues FreeIdentifier)
关于Haskell - 限制数据参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67445966/