2017-10-18 82 views
1

我有一个将输入列表处理为不同类型的函数,但其​​本身并不是有趣的事情。F#将参数配置为高级函数或声明自己的函数

let testList = [(1,"c");(2,"a");(1,"b")] 

let rec toRel xs = 
    let rec insert (a, b) ys = 
     match ys with 
     | []      -> [(a, [b])] 
     | (a', b')::ys' when a' = a -> (a', b::b')::ys' 
     | y::ys'     -> y::insert (a, b) ys' 
    match xs with 
    | []   -> [] 
    | (a,b)::rest -> insert (a, b) (toRel rest) 

toRel testList //Expected [(1, ["c";"b"]); (2, ["a"])] 

这是很好,并且能够被重构到:

testList |> List.groupBy xs |> List.map (fun (k, v) -> (k, list.map snd v)) 

可以得到相同的结果。

当我试图将这个管道过程封装到函数中时,我遇到了问题。

let toRelHigherOrder xs = List.groupBy xs |> List.map (fun (k, v) -> (k, list.map snd v)) 

toRelHigherOrder testList 

This expression was expected to have type ''a -> 'b' but here has type '(int * string) list

什么给?

+2

通常的答案是,以取代'|>'和''>> –

+3

'List.groupBy'是二元的,你只给它一个参数,所以你可以向前推送一个部分应用的函数,而不是一个列表。 – ildjarn

回答

2

我觉得你管是错误的,它应该是:

testList |> List.groupBy fst |> List.map (fun (k, v) -> (k, List.map snd v)) 

所以你的功能应该是:

let f x = x |> List.groupBy fst |> List.map (fun (k, v) -> (k, List.map snd v)) 
+1

作为@JohnPalmer提到的,它也可以是'let f = List.groupBy fst >> List.map(fun(k,v) - >(k,List.map snd v))',但它可以很容易地运行进入价值限制。 – ildjarn

+0

是的,这就是为什么我没有提到它。尽管价值限制很容易解决,但在这种情况下,我可以通过将它与一个明确的参数保持一致来解决它,因为它是。 – Gustavo

+1

“*,但在这种情况下,我会通过将它留给一个明确的参数来解决它,因为它是这样的。*”对,这就是我的意思。 : - ] – ildjarn