f# - 由于循环引用,确定如何订购 F# 类型的问题

标签 f# functional-programming types reference mutual-recursion

我有一些扩展通用类型的类型,这些是我的模型。

然后,我为 CRUD 操作的每种模型类型提供了 DAO 类型。

我现在需要一个函数,它可以让我找到给定任何模型类型的 id,所以我为一些杂项函数创建了一个新类型。

问题是我不知道如何订购这些类型。目前我在 dao 之前有模型,但我不知何故需要 DAOMisc之前 CityDAOCityDAO之前 DAOMisc ,这是不可能的。

简单的方法是把这个函数放在每个 DAO 中,只引用它之前的类型,所以,State出现在 City 之前如StateCity 有外键关系,所以杂项函数会很短。但是,这让我觉得是错误的,所以我不确定如何最好地解决这个问题。

这是我的杂项类型,其中BaseType是我所有模型的通用类型。

type DAOMisc =
    member internal self.FindIdByType item = 
        match(item:BaseType) with
        | :? StateType as i -> 
            let a = (StateDAO()).Retrieve i
            a.Head.Id
        | :? CityType as i -> 
            let a = (CityDAO()).Retrieve i
            a.Head.Id
        | _ -> -1

这是一种道类型。 CommonDAO实际上有 CRUD 操作的代码,但这在这里并不重要。
type CityDAO() =
    inherit CommonDAO<CityType>("city", ["name"; "state_id"], 
        (fun(reader) ->
            [
                while reader.Read() do
                    let s = new CityType()
                    s.Id <- reader.GetInt32 0
                    s.Name <- reader.GetString 1
                    s.StateName <- reader.GetString 3
            ]), list.Empty
    )

这是我的模型类型:
type CityType() =
    inherit BaseType()
    let mutable name = ""
    let mutable stateName = ""
    member this.Name with get() = name and set restnameval=name <- restnameval
    member this.StateName with get() = stateName and set stateidval=stateName <- stateidval
    override this.ToSqlValuesList = [this.Name;]
    override this.ToFKValuesList = [StateType(Name=this.StateName);]

这样做的目的FindIdByType功能是我想找到外键关系的 id,所以我可以在我的模型中设置值,然后让 CRUD 函数使用所有正确的信息进行操作。所以,City需要州名的 id,所以我会得到州名,将其放入 state键入,然后调用此函数以获取该州的 id,因此我的城市插入还将包括外键的 id。

这似乎是最好的方法,以一种非常通用的方式处理插入,这是我正在尝试解决的当前问题。

更新:

在定义了所有其他 DAO 之后,我需要研究并查看是否可以以某种方式将 FindIdByType 方法注入(inject) CommonDAO,就好像它是一个闭包一样。如果这是 Java,我会使用 AOP 来获得我正在寻找的功能,但不确定如何在 F# 中执行此操作。

最后更新:

在考虑了我的方法后,我意识到它有致命的缺陷,所以我想出了一个不同的方法。

这就是我将如何进行插入,我决定将这个想法放入每个实体类中,这可能是一个更好的想法。
member self.Insert(user:CityType) =
    let fk1 = [(StateDAO().Retrieve ((user.ToFKValuesList.Head :?> StateType), list.Empty)).Head.Id]
    self.Insert (user, fk1)

我还没有开始使用fklist然而,但它是int list我知道每个列的名称,所以我只需要做inner join例如,对于选择。

这是泛化的基本类型插入:
member self.Insert(user:'a, fklist) =
    self.ExecNonQuery (self.BuildUserInsertQuery user)

如果 F# 可以做协方差,那就太好了,所以我必须解决这个限制。

最佳答案

这个例子与我在函数式编程中所习惯的相差甚远。但是对于相互递归类型的排序问题,有一个标准的解决方案:使用类型参数,做两级类型。我将在 OCaml(一种相关语言)中给出一个简单的示例。我不知道如何将这个简单的例子翻译成你正在使用的可怕的类型函数。

这是不起作用的:

type misc = State of string
          | City  of city

type city = { zipcode : int; location : misc }

以下是使用两级类型修复它的方法:
type 'm city' = { zipcode : int; location : 'm }

type misc = State of string
          | City of misc city'
type city = misc city'

这个例子是 OCaml,但也许你可以推广到 F#。希望这可以帮助。

关于f# - 由于循环引用,确定如何订购 F# 类型的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2854145/

相关文章:

scala - 在函数式编程术语中,您将 orElse 或其他回退方法称为什么?

haskell - Haskell 什么时候提示函数输入不正确?

f# - 如何使不可变的 F# 性能更高?

F# 等价于 Enumerable.OfType<'a>

arrays - 有没有一种简单的方法可以在 Fsharp 中将 byte [] 转换为 ReadOnlySpan<byte> ?

Python ndarray 具有不同类型的元素

c++ - 如何在 C++ 中转换指针

wpf - 如何在 F# 中使用 WPF 菜单和对话框?

haskell - Haskell 有没有一种简单的方法来实现快速优先级队列?

R 元编程 : pass expression/quosure to function that partially accesses local frame