确定变量类型的最佳方法,并在F#中以不同方式对待每个变量

时间:2010-05-12 00:36:49

标签: f# functional-programming

我有一个函数可以创建一个select where子句,但是现在一切都必须是一个字符串。

我想查看传入的变量并确定它是什么类型然后正确处理它。

例如,数值周围没有单引号,选项类型将为null或具有某个值,布尔值实际上为零或一。

member self.BuildSelectWhereQuery (oldUser:'a)  =  //'
    let properties = List.zip oldUser.ToSqlValuesList sqlColumnList 
    let init = false, new StringBuilder()
    let anyChange, (formatted:StringBuilder) = 
        properties |> Seq.fold (fun (anyChange, sb) (oldVal, name) ->
            match(anyChange) with
            | true -> true, sb.AppendFormat(" AND {0} = '{1}'", name, oldVal)
            | _ -> true, sb.AppendFormat("{0} = '{1}'", name, oldVal)
        ) init
    formatted.ToString()

这是一个实体:

type CityType() =
    inherit BaseType()
    let mutable name = ""
    let mutable stateId = 0
    member this.Name with get() = name and set restnameval=name <- restnameval
    member this.StateId with get() = stateId and set stateidval=stateId <- stateidval
    override this.ToSqlValuesList = [this.Name; this.StateId.ToString()]

因此,如果name除了字符串之外还有其他值,或者stateId可以是可选的,那么我需要进行两项更改:

  1. 如何修改ToSqlValuesList 有变量,所以我可以告诉 变量型?
  2. 如何更改我的选择功能 处理这个?
  3. 我在想我需要一个新的函数来处理,但是最好的FP方法是什么,而不是使用类似typeof的东西?

2 个答案:

答案 0 :(得分:3)

您可以在匹配中使用类型测试模式。这会满足你的需求吗?

let f (x : obj) =
    match x with
    | :? int -> "int"
    | :? string -> "string"
    | :? bool -> "bool"
    | _ -> "who knows?"

答案 1 :(得分:2)

我认为一种明确的功能方法是定义一种数据类型,代表您需要处理的各种(更复杂的情况)。您提到值可能是可选的,您需要区分数值和文本值(对于编码为SQL)。

您可以定义一个有区别的联合(如果您还有其他情况需要处理,那么定义可能会更复杂一些):

type SqlValue = 
  | Missing
  | Numeric of string
  | Textual of string

请注意,Textual情况也带有string,因为我假设生成该值的客户端负责将其转换为字符串 - 这只是您的SQL查询生成器的信息(这样它知道是否需要添加引号。

您的ToSqlValuesList成员会返回值string & SqlValue的列表,例如,可以使用以下列表表示示例产品:

columns = [ "Name"; "Price"; "Description" ]
values = [ Textual("Tea"); Numeric(10); Missing ]

在生成SQL查询的代码中,您将使用模式匹配来处理所有不同的情况(最重要的是,编码字符串以避免SQL注入,以防值为Textual: - ))。< / p>

编辑您需要在每个客户端实现从特定数据类型到SqlValue表示的转换。但是,这可以通过编写实用程序类型(使用成员可以重载的事实)来简化:

type SqlValue with 
  static member From(a:int) = Numeric(a.ToString())
  static member From(a:int option) = 
    match a with None -> Missing | Some(n) -> SqlValue.From(n)
  // ... similarly for other types

ToSqlValuesList的实现中,您可以编写SqlValue.From(description)并自动处理详细信息。

更复杂的方法是使用.NET属性注释表示数据实体的类型的公共成员,并使用Reflection在运行时提取值(及其类型)。这是更先进的,但相当优雅(在Don Syme的专家F#书中有一个很好的例子)