Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 是否有一个现有的模式来为两个列表中的每个项目组合生成一个函数应用程序列表?_F#_Functional Programming_Terminology - Fatal编程技术网

F# 是否有一个现有的模式来为两个列表中的每个项目组合生成一个函数应用程序列表?

F# 是否有一个现有的模式来为两个列表中的每个项目组合生成一个函数应用程序列表?,f#,functional-programming,terminology,F#,Functional Programming,Terminology,我刚刚开始学习函数式编程,我正处于“尝试一些不平凡的例子,问问别人我是否做错了”阶段。我遵循Don Syme的建议,决定尝试一下第二部分末尾的21点练习,但有一个转折点:为了简单起见,他建议将Ace视为11,但我决定忽略这一建议 我处理它的方法是给每个卡片等级一个可能值的列表,并递归地建立一个可能手值的列表,因此: let cardValues (Card(rank, _)) = match rank with | Ace -> [1; 11

我刚刚开始学习函数式编程,我正处于“尝试一些不平凡的例子,问问别人我是否做错了”阶段。我遵循Don Syme的建议,决定尝试一下第二部分末尾的21点练习,但有一个转折点:为了简单起见,他建议将Ace视为11,但我决定忽略这一建议

我处理它的方法是给每个卡片等级一个可能值的列表,并递归地建立一个可能手值的列表,因此:

let cardValues (Card(rank, _)) =
    match rank with
    | Ace                 -> [1; 11]
    | King | Queen | Jack -> [10]
    | Value(value)        -> [value]

let rec handValues = function
    | [] -> [0]
    | card::cards ->
        [
            for handValue in handValues cards do
                for cardValue in cardValues card do
                    yield handValue + cardValue
        ]

handValues
函数在结构上与折叠非常相似,我无法摆脱这种感觉,我已经可以使用一些高阶函数来实现这一点。我有什么遗漏吗?或者这是一个正确的方向吗?

我认为你的解决方案已经很好了

折叠在您的情况下不起作用。我们可以折叠一组数字,也可以折叠两组数字。但在你的情况下,这不仅仅是两个数字列表


考虑一个极端情况,即您的列表包含长度为n的所有ACE,则有2^n个可能的值。要列举所有可能性,您需要dfs搜索或bfs搜索。您的代码实际上相当于bfs搜索(因此需要更多内存),尽管它是以递归方式编写的。

我认为您的解决方案已经很好了

折叠在您的情况下不起作用。我们可以折叠一组数字,也可以折叠两组数字。但在你的情况下,这不仅仅是两个数字列表


考虑一个极端情况,即您的列表包含长度为n的所有ACE,则有2^n个可能的值。要列举所有可能性,您需要dfs搜索或bfs搜索。您的代码实际上相当于bfs搜索(因此需要更多内存),尽管它是以递归方式编写的。

您的操作方式非常好。可以将列表上的任何递归函数表示为折叠,但我认为这样做不会带来任何好处。也没有内置函数来精确执行您需要的操作,但是您可以构建一个更通用的函数,并在此基础上构建特定的计算。这里有一种方法:

let rec allChoices = function
| [] -> [[]]
| l::ls ->
    [for x in l do
     for xs in allChoices ls do
       yield x::xs]

let values hand = 
  hand |>
  List.map cardValues |>
  allChoices |> 
  List.map (List.sum)
allChoices
函数获取列表列表,并返回每个列表中包含单个元素的每个可能列表(例如
allChoices[[1];[2;3];[4;5]=[1;2;4];[1;2;5];[1;3;4];[1;3;5]
)。我们使用此函数获取手牌中所有可能的值列表,然后对每个列表求和


你可能还有其他几种方法来看待这个问题,这些方法可能会带来其他的变化。

你做事情的方式非常好。可以将列表上的任何递归函数表示为折叠,但我认为这样做不会带来任何好处。也没有内置函数来精确执行您需要的操作,但是您可以构建一个更通用的函数,并在此基础上构建特定的计算。这里有一种方法:

let rec allChoices = function
| [] -> [[]]
| l::ls ->
    [for x in l do
     for xs in allChoices ls do
       yield x::xs]

let values hand = 
  hand |>
  List.map cardValues |>
  allChoices |> 
  List.map (List.sum)
allChoices
函数获取列表列表,并返回每个列表中包含单个元素的每个可能列表(例如
allChoices[[1];[2;3];[4;5]=[1;2;4];[1;2;5];[1;3;4];[1;3;5]
)。我们使用此函数获取手牌中所有可能的值列表,然后对每个列表求和


您可能还有其他几种方法来看待这个问题,这些方法可能会带来其他变化。

值得一提的是

    [ 
        for handValue in handValues cards do 
            for cardValue in cardValues card do 
                yield handValue + cardValue 
    ] 
是一元束缚;可以编写一个“列表”单子,然后使用计算表达式将其编写为

listMonad {
    let! handVal = handValues cards
    let! cardVal = cardValues card
    return hardVal + cardVal
}

值得一提的是

    [ 
        for handValue in handValues cards do 
            for cardValue in cardValues card do 
                yield handValue + cardValue 
    ] 
是一元束缚;可以编写一个“列表”单子,然后使用计算表达式将其编写为

listMonad {
    let! handVal = handValues cards
    let! cardVal = cardValues card
    return hardVal + cardVal
}

+1是的,绝对值得一提@布莱恩:是否有一个有用的monad构建器的内置集合(列表,也许,异步,状态…)?不,只是异步在FSharp.Core中。您可能会在web上找到一些示例,如选项(又称为maybe)、列表和状态;把他们聚集到网上某个地方的开源项目中不会有什么坏处。这正是我在我的问题中想要的优雅。现在要弄清楚这些一元绑定的东西是关于什么的>是的,它是这个问题的一个非常优雅的解决方案,或者任何一个你从一个产生一个答案的算法开始,然后把它推广到可以产生多个答案的组件中。。。您可以将所有组件“提升”到monad中,将“let”更改为“let!”在不同的地方,瞧,现在你找到了所有可能的解决方案。如果你花些时间钻研F#计算表达式和单子后无法实现这一点,请告诉我,我会再编写一些代码。这总是让我感到困惑。在F#中,原则上可以根据
let/
返回
,但在
/
收益率方面也是如此。这两者之间真的没有区别。当然,在monad中使用
for
是根据
let/
返回
是有意义的,但情况并非如此。因此,我能看到的上述两个定义之间的唯一区别是,使用序列表达式的定义会更快(因为F#编译器对其进行了优化)。因为F#代码不能用monad类型参数化,所以它在任何方面都不是更通用的…+1是的-绝对值得一提@布莱恩:是否有一个有用的monad构建器的内置集合(列表,也许,异步,状态…)?不,只是异步在FSharp.Core中。您可能会在web上找到一些示例,如选项(又称为maybe)、列表和状态;把他们聚集到网上某个地方的开源项目中不会有什么坏处。这正是我在我的问题中想要的优雅。现在到