从元组检索值时无法解决有关“选项”的错误

时间:2015-12-19 18:48:04

标签: f#

我只是不明白编译器在这里告诉我的是什么:

let someCard = getFirstCard hand

错误:

  

该表达式预计具有类型
        Card * Card
    但这里有类型
        (Card * Card) option

然后我尝试了这个:

let getFirstCard (hand:Card*Card) = function
    | card1, card2 -> Some(card1)

但我得到同样的错误。

我只是没有获得选项模板。 我继续为此而奋斗。

我的代码如下:

type Suit = | Spades| Clubs | Diamonds | Hearts

type Face = | Two | Three | Four | Five 
            | Six | Seven | Eight | Nine | Ten
            | Jack | Queen | King | Ace

type Card = {Face:Face; Suit:Suit}

type Deal = | Hand of Card * Card
            | Hit of Card

let private suits = [Spades; Clubs; Diamonds ; Hearts]
let private faces = [Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
                     Jack; Queen; King; Ace]

let deck = [for suit in suits do
                for face in faces do
                    yield {Face=face; Suit=suit}]

let hitPlayer (deck:Card list) =
    (deck.Head, deck.Tail)

let shuffle xs =
    let swap i j (array : _[]) =
        let tmp = array.[i]
        array.[i] <- array.[j]
        array.[j] <- tmp
    let rnd = System.Random()
    let xArray = Seq.toArray xs
    let n = Array.length xArray
    for i in [0..(n-2)] do
        let j = rnd.Next(i, n-1)
        swap i j xArray
    xArray |> Seq.toList

let deal = function
    | card1::card2::remaining -> Some(card1, card2), remaining
    | _ -> None, [];;

let getFirstCard (hand:Card*Card) = function
    | card1, card2 -> card1

let hand, deckRemaining = deal (shuffle deck);;
let someCard = getFirstCard hand

2 个答案:

答案 0 :(得分:4)

getFirstCard函数的类型为Card * Card -> 'a * 'b -> 'a(BTW,看起来很奇怪,至少可以说)。但是,它确实希望其第一个参数属于Card * Card类型。

另一方面,

hand(双关语),类型为(Card * Card) option。这意味着可能包含Card * Card值,但也可能不包含let someCard = hand |> Option.map getFirstCard 值。您需要告诉您的程序如何处理这两种情况。

作为we've discussed before,选项类型是一个“升级的世界”,最合适的策略是保持在这个高架世界,直到您可以处理所有案例。这是一种方法:

getFirstCard

由于getFirstCard的奇怪实现,这仍然无效。

然而,看看let getFirstCard (card1, card2) = card1 的实现情况,我得到的印象是,您尝试做的是从卡片组中取出第一张卡片。但是,这可以写成:

let getFirstCard = fst

该功能已内置于F#中,但为其提供特定于域的名称并没有错。但是,在这种情况下,我建议改为别名:

getFirstCard

鉴于以上两个let someCard = hand |> Option.map getFirstCard 的定义之一,表达式

someCard

为您提供Card option类型的someCard值。你会注意到我们一直待在高架地区。 选项世界。

具体而言,> someCard;; val it : Card option = Some {Face = King; Suit = Clubs;} 具有此值:

files <- list.files("C:\\New folder", "*.bin",full.names=TRUE)
for (i in 1:length(files)) {
conne <- file(files[i], "rb")
file  <- readBin(conne, double(), size=4,  n=300*700, signed=TRUE)
file2 <- matrix(data=file,ncol=700,nrow=300)
                           }

你会注意到它不仅仅是俱乐部之王,而是 一些 俱乐部之王

答案 1 :(得分:1)

试试这个:

let getFirstCard (hand) = 
    match hand with 
    | Some(x) -> Some (fst x)
    |_ -> None

let hand, deckRemaining = deal (shuffle deck);;
let someCard = getFirstCard hand

它编译&amp;跑来跑去。

实际上,函数getFirstCard可以重命名为元组的通用乐趣:

let getFirstOfTupleOption tup =
    match tup with
    | Some (x) -> Some (fst x)
    | _ -> None

或者,您可能希望对您的域明确表示类型限制:

let getFirstCard (hand:(Card*Card) option) = 
    match hand with 
    | Some(x) -> Some (fst x)
    |_ -> None