如何使我的功能通用

Posted

技术标签:

【中文标题】如何使我的功能通用【英文标题】:How to make my function generic 【发布时间】:2011-05-12 03:29:45 【问题描述】:
    let csvList startDelim endDelim lst memF = 
        let listIter (listStr: string) item = 
            if listStr.Length > 0 then 
                listStr + "," + (memF item)
            else 
                memF item                
        startDelim + (List.fold listIter "" lst) + endDelim

    let listIntoJsonArray = csvList "[" "]"
    let listIntoJsonObject = csvList "" ""

    let intConverter (item:int) : string =
        item.ToString()

    let objectConverter (item:SomeObject) : string =
        item.value.ToString()

    let objects = [vaue: 12.3; vaule: 33.2]
    let ints = [1;2;4]

    let o = listIntoJsonObject objects objectConverter
    let i = listIntoJsonObject ints intConverter 

我似乎找不到使 csvList 或其部分应用的助手 listIntoJsonArray 或 listIntoJsonObject 通用的秘诀。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

您的 listIntoJsonArray 和 listIntoJsonObject 是值,而不是函数,所以您遇到了 value restriction 怪物。您可以通过添加显式参数或类型函数将它们转换为函数。

// function case

let csvList startDelim endDelim lst memF = 
    let listIter (listStr: string) item = 
        if listStr.Length > 0 then 
            listStr + "," + (memF item)
        else 
            memF item                
    startDelim + (List.fold listIter "" lst) + endDelim

let listIntoJsonObject x = csvList "" "" x

let ints = [1;2;4]

let i = listIntoJsonObject [1;2;4] string 
let y = listIntoJsonObject ["123"] id


// type function case

let csvList<'T> startDelim endDelim (lst : 'T list) memF = 
    let listIter (listStr: string) item = 
        if listStr.Length > 0 then 
            listStr + "," + (memF item)
        else 
            memF item                
    startDelim + (List.fold listIter "" lst) + endDelim

[<GeneralizableValue>]
let listIntoJsonObject<'T> = csvList<'T> "" ""

let ints = [1;2;4]

let i = listIntoJsonObject [1;2;4] string 
let y = listIntoJsonObject ["123"] id

【讨论】:

【参考方案2】:

我没有尝试过代码,但一般来说,eta-conversion,例如改变

let myFunVal = partialApplication toSomeArgs

let myFun rest = partialApplication toSomeArgs rest

很可能会解决这个问题。

【讨论】:

【参考方案3】:

csvList 看起来足够通用:string -&gt; string -&gt; 'a list -&gt; ('a -&gt; string) -&gt; string

但是您在尝试使用listIntoJsonArraylistIntoJsonObject 进行部分应用时遇到了Value Restriction;您需要添加显式参数:

let listIntoJsonArray lst memF = csvList "[" "]" lst memF
let listIntoJsonObject lst memF = csvList "" "" lst memF

【讨论】:

似乎没有成功。就在我感觉自己已经牢牢掌握了这门语言的时候,它需要另一个转折点。需要更多地研究价值限制......谢谢。 @akaphenom:我最初的解决方案有一个错误(我将参数添加到函数定义中,但后来没有将它们作为参数传递给 csvList),它现在应该可以正常工作了。 F# 是一头野兽,但这让驯服变得更加令人兴奋,奖励也更加丰厚:)

以上是关于如何使我的功能通用的主要内容,如果未能解决你的问题,请参考以下文章

如何使我的 spriteNode 纹理通用?

如何安全地赋予我的功能而不使我的主要形式卡住

如何在进行选择之前使我的代码中的复选框默认为未选中,同时保持我的功能相同?

如何使我的 Python 程序提供的功能可用于在同一台或其他计算机上运行的以其他语言编写的程序?

如何检测 IOS 7 和 IOS 8 以及宽屏 iPhone 尺寸以使我的应用程序通用?

为啥我必须执行两次按钮功能才能使我的逻辑正常工作?