F#对于列表中的每个元素,应用功能,在列表元素中,b
鉴于以下组代表一个存储类型:F#对于列表中的每个元素,应用功能,在列表元素中,b
type Article = string type Amount = int
type Price = int
type Desc = Amount*Price
type Stock = (Article*Desc) list
type Order = Article * Amount
type Status<'a> = Result of 'a | Error of string
我想打一个函数,它接受一个Order
和Stock
和回报一个Status<Price * Stock>
。下面get (a,k) st
所定义的函数的值是Result (p,st')
其中p
是k
件a
和st'
价格是通过除去k
件a
从st
获得的新的库存。
例子:
let rec get (a,k) st = match st with
| (a',(n',p'))::rest when a'=a -> Result (p'*k,(a',(n'-k,p'))::rest)
| (a',(n',p'))::rest ->
match get (a,k) rest with
| Result (price,stock) -> Result (price,(a',(n',p'))::stock)
| Error e -> Error e
get ("a2", 10) st
val it : int * (string * (int * int)) list =
Result (200, [("a1", (100, 10)); ("a2", (40, 20)); ("a3", (25, 40))])
现在,我怎么会去这样做,如果我花了一个Order list
?
如get [("a2",10);("a1",10)] st
将返回Result (300, [("a1", (90, 10)); ("a2", (40, 20)); ("a3", (25, 40))])
回答:
type Article = string type Amount = int
type Price = int
type Desc = Amount * Price
type Stock = (Article * Desc) list
type Order = Article * Amount
type Status<'a> = Result of 'a | Error of string
首先,既然你问了功能get
的实现,让我们重命名现有功能get
为getArticle
。
let rec getArticle (a, k) st = match st with
| (a', (n', p')) :: rest when a' = a -> Result (p' * k, (a', (n' - k, p')) :: rest)
| (a', (n', p')) :: rest ->
match getArticle (a, k) rest with
| Result (price, stock) -> Result (price, (a', (n', p')) :: stock)
| Error e -> Error e
| [] -> Error "Article not in stock"
我还添加了一个额外的案例来摆脱“不完整模式匹配”警告。
您的问题的答案是List.fold
。
List.fold
的第一个参数是类型为'State -> 'ElementType -> 'State
的文件夹函数。在这个问题上,'ElementType
是Order
。
getArticle
几乎做了什么文件夹功能应该做的:计算下一个状态,当遍历一个元素 - 在这个问题:一个订单 - 在列表中。但并不完全:
getArticle
作为输入说出一个Stock
但回报作为输出状态的Status<Price * Stock>
,其中附加Price
是检索文章的总价格(到目前为止)。List.fold
预计文件夹功能的输入和输出状态是相同的类型。getArticle
将第一个参数作为第一个参数,该列表中的元素的类型为Order
- ,第二个参数为输入状态。List.fold
预计需要交换这两个参数的文件夹函数。
所以,让我们constuct文件夹功能,其中,(加)检索到的文章至今累积的总价格:
let folder status order = match status with
| Result (totalPriceSoFar, stock) ->
match getArticle order stock with
| Result (price, st) -> Result (totalPriceSoFar + price, st)
| Error e -> Error e
| Error f -> Error f
我们现在几乎完成。
List.fold
的第二个参数是初始状态 - 在此问题中:初始库存为Result
,目前总价格初始化为0
。
的List.fold
第三个参数是列表中要迭代 - 在这个问题:订单列表。
let get orders initialStock = let initialStatus = Result (0, initialStock)
List.fold folder initialStatus orders
let initialStock = [("a1", (100, 10)); ("a2", (50, 20)); ("a3", (25, 40))]
get [("a2", 10); ("a1", 10)] initialStock
关闭的话
您选择定义的类型Stock
为(Article * Desc) list
。鉴于您基本上使用此列表作为查找地图,其中文章不能有2个价格或2个数量,为什么不选择Map<Article, Desc>
?
以上是 F#对于列表中的每个元素,应用功能,在列表元素中,b 的全部内容, 来源链接: utcz.com/qa/263451.html