为了表示DSL语法树,我有表示该树的数据类型.在这个树的几个地方,我得到了许多可选的子元素和/或具有"*"多样性.所以一种数据类型可能看起来像
data SpecialDslExpression = MyExpression String [Int] Double [String] (Maybe Bool)
Run Code Online (Sandbox Code Playgroud)
我正在寻找的是构建这样一种类型而不必指定所有参数的可能性,假设我有一个有效的默认值.使用场景是这样的,我需要创建许多类型的实例,其中给出或省略了其参数的各种组合(大多数时间是两个或三个),但很少都是这些.将参数分组为子类型不会让我走得太远,因为参数组合不遵循会使分段改善问题的模式.
我可以使用不同的参数组合来定义函数,以使用其余的默认值来创建类型,但是我可能最终会有很多这些函数很难正确命名,因为可能无法给出正确的名称.createWithFirstAndThirdParameter在给定的背景下的想法.
所以最后问题归结为:是否有可能创建这样的数据类型或对它的抽象,这会给我一些像我可以指定的可选参数或希望省略的东西?
kqr*_*kqr 12
我建议使用镜头组合和默认实例.如果您尚未导入Control.Lens一半模块,现在是时候开始了!无论如何,镜头到底是什么?镜头是一个吸气剂,一个装订器捣碎成一个功能.它们非常易于组合.任何时候您需要访问或修改数据结构的某些部分,但您认为记录语法不实用,镜头就在那里.
所以,你需要做的第一件事 - 启用TH和导入Control.Lens.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
Run Code Online (Sandbox Code Playgroud)
您需要对数据类型进行的修改是为所有字段添加名称,如下所示:
data SpecialDslExpression = MyExpression { _exprType :: String
, _exprParams :: [Int]
, _exprCost :: Double
, _exprComment :: [String]
, _exprLog :: Maybe Bool
} deriving Show
Run Code Online (Sandbox Code Playgroud)
对于以下步骤,字段名称开头的下划线很重要.因为现在我们想为这些领域生成镜头.我们可以要求GHC使用Template Haskell为我们做这件事.
$(makeLenses ''SpecialDslExpression)
Run Code Online (Sandbox Code Playgroud)
然后,最后需要做的是构建一个"空"实例.请注意,没有人会静态检查您是否实际填写了所有必填字段,因此您最好添加一个error字段,以便至少获得运行时错误.像这样的东西:
emptyExpression = MyExpression (error "Type field is required!") [] 0.0 [] Nothing
Run Code Online (Sandbox Code Playgroud)
现在你准备好了!你不能使用emptyExpression,它将在运行时失败:
> emptyExpression
MyExpression {_exprType = "*** Exception: Type field is required!
Run Code Online (Sandbox Code Playgroud)
但!只要你填充类型字段,你将是金色的:
> emptyExpression & exprType .~ "Test expression"
MyExpression { _exprType = "Test expression"
, _exprParams = []
, _exprCost = 0.0
, _exprComment = []
, _exprLog = Nothing
}
Run Code Online (Sandbox Code Playgroud)
如果需要,您还可以一次填写多个字段.
> emptyExpression & exprType .~ "Test expression"
| & exprLog .~ Just False
| & exprComment .~ ["Test comment"]
MyExpression { _exprType = "Test expression"
, _exprParams = []
, _exprCost = 0.0
, _exprComment = ["Test comment"]
, _exprLog = Just False
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用镜头将函数应用于字段,或查看字段的字段,或修改任何其他现有表达式等.我绝对建议你看看你能做些什么!
Dan*_*zer 11
好吧,我实际上会扩展我的评论.首先,将您的数据类型定义为记录(并输入几个类型的同义词).
data Example = E {
one :: Int,
two :: String,
three :: Bool,
four :: Double
}
Run Code Online (Sandbox Code Playgroud)
接下来,您将创建一个默认实例
defaultExample = Example 1 "foo" False 1.4
Run Code Online (Sandbox Code Playgroud)
然后当用户想要调整默认字段中的字段来创建自己的数据时,他们可以这样做:
myData = defaultExample{four=2.8}
Run Code Online (Sandbox Code Playgroud)
最后,当他们想要模式匹配一个项目时,他们可以使用
foo MyData{four=a} = a
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
444 次 |
| 最近记录: |