我正在尝试对位置列表中的每个位置(列表)进行排序。目前我这样做:
type Position = Position of list<int * Piece>
和我的职能:
let SortPositionList positionList : Position list =
let rec loop list =
match (list: Position list) with
| [] -> []
| hd::tl -> [List.sortBy(fun (x:(int*Piece)) -> fst x)(GetInternStruct(hd))::loop tl]
loop positionList
在我看来,这可以通过递归排序列表的实际头部然后将其与列表的其余部分连接来完成,但它不起作用。此函数中的错误是:
类型不匹配。期望一个(int * Piece)列表列表但给出一个(int * Piece)列表列表类型'int * Piece'与类型'(int * Piece)列表'不匹配,带下划线的loop tl
< / p>
类型不匹配。期望一个位置列表,但给出一个(int * Piece)列表列表列表类型'Position'与类型'(int * Piece)列表'不匹配,在下划线调用loop,loop positionList
希望你能提前帮助
Pedro Dusso
修改 AList.map传递排序函数会是一个很好的方法吗?
解
let SortPositionList (positionList : Position list) =
List.map (fun (Position(position)) -> List.sort(position)) positionList
由于我的Position结构是一个(int * Piece)lst,我在无穷大的函数中对它进行模式匹配并对其进行排序。
感谢您的回答!
答案 0 :(得分:4)
如何:
let SortPositionList (positionList : Position list) =
List.map (fun pos -> List.sortBy (fun (index, _) -> index) pos) positionList
您正在使用的是位置列表上的List.map,将每个元素(本身为列表)映射到List.sortBy函数。这需要一个返回键进行比较的函数。在这种情况下,我们使用内置模式匹配来匹配'int * Piece'元组中的索引。
答案 1 :(得分:3)
一般来说,F#中有两种处理方式。您可以显式使用递归,也可以使用现有函数。在您的情况下,您需要以嵌套方式执行两项操作 - 您需要遍历外部列表并对内部列表进行排序。排序可以使用List.sortBy
完成,迭代(投影)可以使用List.map
完成。
要纠正你的原始方法(使用递归) - 我稍微简化了一下(因为你不需要loop
函数 - 你可以使函数本身递归):
let rec sortPositionList list =
match list with
| [] -> []
| hd::tl ->
// Sort the list of positions first - by storing this as a new value
// using 'let', you get more readable code (and you can use IntelliSense
// to explore the type of 'sorted' and understand what's going on)
let sorted = List.sortBy (fun (x, _) -> x) (GetInternStruct(hd))
// As Brian suggests, more idiomatic F# encoding of the line would be:
// let sorted = GetInternStruct(hd) |> List.sortBy (fun (x, _) -> x)
// but both of the options would work in this case.
// Note: The result shouldn't be wrapped in '[ .. ]'. The operator '::'
// takes an element and a list and returns a new list created by
// prepending the element in front of the list
sorted::(sortPositionList tl)
使用现有功能(List.map
)的解决方案已由JDU发布。我只想补充一点,他使用部分函数应用程序 - 所以传递给List.map
的参数是一个函数。如果这让人感到困惑,你可以明确地使用lambda函数重写它:
let SortPositionList (positionList) =
List.map (fun positions ->
List.sortBy (fun (index, _) -> index) positions) positionList
使用流水线操作符和fst
函数而不是显式lambda参数(如Brian所提到的),可以更加惯用地编写:
let SortPositionList (positionList) =
positionList |> List.map (fun positions ->
positions |> List.sortBy fst)
这意味着与JDU发布的代码完全相同,但您可能会发现它更具可读性。最后,你可以使用序列表达式编写相同的东西(在我看来,这可能是最优雅的选项):
let SortPositionList (positionList) =
[ for positions in positionList do
yield positions |> List.sortBy fst ]
编辑我在这里编写的函数使用的是(int*Point) list list
类型的值,而不是Positions list
类型的值。要更改此设置,您需要添加一些包装和展开。递归实现应该是:
match list with // List is always 'Positions', so we use pattern
| Positions [] -> [] // matching to unwrap the underlying list in
| Positions (hd::tl) -> // both cases
// Wrap the resulting list into the positions type
let sorted = Positions(List.sortBy (fun (x, _) -> x) (GetInternStruct(hd)))
(sorted::(sortPositionList tl))
同样,对于List.map
实施:
let SortPositionList (positionList) =
positionList |> List.map (fun (Positions positions) -> // pattern matching
positions |> List.sortBy fst |> Positions) // wrapping
答案 2 :(得分:2)
你做错了。 :)
我不知道你要做什么,但看着你的代码,我只知道这是错的,所以这就是我所看到的。
首先,你有
... List.sortBy blah1 blah2 ...
这是非惯用的,你想要
... blah2 |> List.sortBy blah1 ...
这将有助于类型推断。这种情况分为第二个问题,即
(fun (x:(int*Piece)) -> fst x)
是胡说八道。你可以写
(fun (i:int,p:Piece) -> i)
或
(fun (i,p) -> i)
或只是
fst
这意味着同样的事情,但你写的东西对人类来说是难以理解的(无论如何)。我希望也许你最初可能因为没有管道启动而陷入困境。
最后,更多的是,代码示例中缺少空格也使其无法读取;
)(
中间没有空格,并使用更多的水平和垂直空格来使代码的解析更加明显。
这主要是风格和肤浅的反馈,但我认为如果你解决这个问题,那些没有解决的类型的深层问题将开始变得更有意义并且变得更加明显。
答案 3 :(得分:1)
let apply f (Position xs) = Position(f xs)
let sorts = List.map (apply List.sort)