【问题标题】:F# won't pattern match all elements of a listF# 不会匹配列表的所有元素
【发布时间】:2019-10-06 08:43:27
【问题描述】:

我编写了一个递归函数 doMoves,它应该匹配列表的每个元素并调用指定的函数。但是,我运行了一个列表 [Draw; Draw],其中 Draw 函数只被调用一次。我不确定为什么它不匹配每个元素。

我写了一个递归函数,它应该在每一步都取一个列表的头部并将它与一个函数匹配

let officiate (cards:Card list) (moves:Move list) (goal:int) = 
  let mutable heldCards = []
  let mutable deck = cards

  let doNothing = 
    heldCards

  let DrawCard = 
    lazy (
    heldCards<-List.append heldCards [deck.Head]
    List.length heldCards |> printfn "Length of Drawn heldCards: %d"
    deck<-deck.Tail)

  let rec doMoves movs = 
    match movs with
    | [] -> doNothing
    | x::xs -> 
      match x with
        | Draw -> DrawCard.Force()
      doMoves xs
  doMoves moves
  true

let moves = [Draw; Draw]
let cards = [(Jack,Clubs); (Num(8),Diamonds)]
let card = (Jack,Spades)
officiate cards moves 42

我希望输出状态

Length of Drawn heldCards: 1
Length of Drawn heldCards: 2

但我得到以下信息:

Length of Drawn heldCards: 1

【问题讨论】:

  • DrawCard 不是一个函数,它是一个值。它不会在您每次提及时都执行,它只会在初始化时计算一次
  • 我用惰性执行它,但它仍然只执行一次。
  • 您将其设为延迟初始化值,但仍不是函数。如果你想让它被多次评估,你需要把它变成一个函数。
  • 为了扩展 Fyodor Soikin 所说的,let x = ... 是一个值,但 let x () = ... 是一个函数。要将DrawCard 变成一个函数,您需要给它一个参数,即使该参数只是“单位”参数()

标签: f# pattern-matching


【解决方案1】:

错误是因为 DrawCard 是一个值,而不是一个函数。要在 F# 中编写无参数函数,您需要将单位指定为输入。即

  let drawCard () = //your implementation

我试图以更实用的方式编写我认为您正在尝试做的事情:

 let officiate (cards:Card list) (moves:Move list) (goal:int) =

   let drawCard (heldCards: Card list) (deck: Card list) =
     match deck with
     | [] -> Error "Empty deck"
     | head::tail -> Ok (List.append heldCards [head], tail)

   let rec doMoves heldCards deck movs =
     printfn "Hand is %d, deck is %d." (List.length heldCards) (List.length deck)
     match movs with
     | [] -> heldCards, deck
     | x::xs ->
       match x with
         | Draw ->
             drawCard heldCards deck
             |> function
             | Ok (h, d) -> doMoves h d xs
             | Error s ->
                 printfn "An error occurred: %s" s
                 heldCards, deck
         | Discard c -> failwith "todo"
   doMoves [] cards moves

 let moves = [Draw; Draw]
 let cards = [(Jack,Clubs); (Num(8),Diamonds)]
 officiate cards moves 42

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-16
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2020-09-25
    • 2020-07-31
    相关资源
    最近更新 更多