genericsf#value-restriction

How to make my function generic


    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 

I can't seem to find the magic sauce to make the csvList or its partially applied helpers listIntoJsonArray or listIntoJsonObject generic.

Thanks for the help.


Solution

  • Your listIntoJsonArray and listIntoJsonObject are values, not functions, so you met value restriction monster. You can either convert them to functions by adding explicit argument or to type functions.

    // 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