【发布时间】:2017-01-17 05:51:16
【问题描述】:
我的场景是用户输入要执行的文本的 DSL。 text 可以是数字运算,也可以是对字符串或数字的关系运算(返回布尔值)。 在用户输入中可以是常量值或变量(其中变量值必须从另一个源/字典中获取并用于操作)
例子(数字运算)
(1 + 2)
(@variableName@ + 2) //returns int
关系运算示例
(@countryname@ in {abc,def,ghi}) //returns bool over variable with string value
(3 > 5) //returns bool over int
(@VariableInt@ > 5) // bool over variable having int value
我有 DU 用数字表示
type NumberExpression
| VariableName of string //variable name
|Constant of int
| Add of NumberExpression * expression
type RelationExpression
| Boolean of bool
| GT of NumberExpression * NumberExpression
| In of NumberExpression * string list
为了解释我的表达式/变量,我有类似的东西,如果是 variableName,我想从这里返回字符串或 int,这样我的 RelationExpression|In 可以获得字符串值
let rec Interpret input =
match input with
| VariableName(name) ->
let stringvalue,datatype = datadictionary.[name] //assume value is from map. I need to do typecase and either return string or int here???
| Constant(value) ->value
对于变量的数字操作适用于关系表达式,因为它的变量返回类型是 int。现在我必须处理返回字符串值的变量的返回类型。 我的 NumberExpression|variable 如何返回 int/string
我可以尝试创建一个浮点和字符串的鉴别器联合,我的函数将返回这个新的鉴别器联合,但现在的问题是所有默认情况下浮点操作在我的新鉴别器联合上都无效(即使是浮动价值)。
type myResultType =
| Number of float
| StringItem of string
//assume function has some logic to return either float/string
let myFunction input =
match input with
| "F" -> input |> Number
| "S" -> input |> StringItem
// assume some logic to consume float number returned by my function.
let finalValue = (10.0) + (myFunction "200F")
尽管我的函数返回内部浮点数,但它的新联合类型并没有 + 运算符。所以使用 DU 返回任何一种类型的方法对我都不起作用。如何处理?
【问题讨论】:
-
在保持类型安全的同时,没有 du 就无法完成,或者在 du 中添加运算符需要付出很多努力
-
这是一个逻辑问题而不是技术问题。有一些方法可以让它工作,但是当返回字符串时它会在运行时失败,所以我们又来质疑如果它不提供类型安全,为什么要使用 DU。你能提供更多关于你的具体场景的细节吗,看起来设计有问题。
-
既然我看到了你的上下文,我想说你应该在操作中使用它之前评估变量。所以:
let eval (thing:myResultType) = match thing with Number n -> n | StringItem name -> lookupValueOf name。lookupValueOf函数接受一个字符串并返回一个浮点数。那么你就不必再重新定义运算符了:你只需在计算值之前将这些字符串转换为浮点数(因为用户键入他们尚未定义的名称是错误的,对吧?) -
我的变量可以保存字符串/整数值。现在我的lookupValueof 函数必须要么返回一个浮点数/字符串。我的查找源是一个字典,其值为 Tuple("stringvalue"* "DataType")。根据数据类型,我必须将 stringvalue 类型转换为该数据类型。