F#:警告 FS0020:この式のタイプは「unit」である必要がありますが、タイプは「bool」です。

StackOverflow https://stackoverflow.com/questions/1108865

  •  12-09-2019
  •  | 
  •  

質問

オイラー問題をいくつか解いて F# を学ぼうとしていますが、理解できない問題を見つけました。これは私の素朴な解決策です。

let compute =
    let mutable f = false
    let mutable nr = 0
    while f = false do
        nr <- nr + 20
        f = checkMod nr
    nr

これを実行すると、FS0020 を警告するエラー メッセージが表示されます。この式はタイプ「unit」を持つ必要がありますが、式「nr <- nr +20」ではタイプ「bool」になります。式を書き直して移動しようとしましたが、常に while ステートメントの下の行でエラーが発生します。

私はVS2010ベータ版を使用してこれを書いています。

役に立ちましたか?

解決

次の行:

f = checkMod nr

私はあなたが意図していると考えているよう平等性チェックではなく、割り当てです。変更します:

f <- checkMod nr

、すべてが正常に動作する必要があります。あなたが前の行に正しい構文を使用してきた理由は私はわからないではない、その行...

また、ラインwhile f = false doは本当にwhile not f doに簡略化されなければなりません。ブール上の平等のチェックはかなり複雑です。

I側の注意点として、私はあなたが効果的に命令型言語としてのF#を使用しようとしていることを指摘する必要性を感じています。可変変数のとwhileループを使用することを強く純粋に機能的な(かつ簡単)ソリューションは、このような状況のように、存在する場合は特に、(F番号を含む)の関数型言語に落胆しています。私はあなたが機能的なスタイルでのプログラミング上のビットを読んでお勧めします。もちろん、ただの構文でグリップを得ることは、それ自体に便利なものです。

他のヒント

この weg ページが情報を検索するための「正規」の場所になると想像できるので、 警告 FS0020, ここでは、警告が表示される最も一般的な 3 つのケースとその修正方法を簡単にまとめました。

副作用のためだけに呼び出された関数の結果を意図的に破棄します。

// you are calling a function for its side-effects, intend to ignore result    
let Example1Orig() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi")       // warning FS0020
    sb.Append(" there")   // warning FS0020
    sb.ToString()

let Example1Fixed() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi") |> ignore
    sb.Append(" there") |> ignore
    sb.ToString()

警告はエラーを指摘するのに役立ちます (関数は効果がありません)。

// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l    // warning FS0020
    printfn "doubled list is %A" l

let Example2Fixed() =
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l
    printfn "doubled list is %A" result

紛らわしい代入演算子と等価比較演算子:

// '=' versus '<-'
let Example3Orig() =
    let mutable x = 3
    x = x + 1          // warning FS0020
    printfn "%d" x    

let Example3Fixed() =
    let mutable x = 3
    x <- x + 1
    printfn "%d" x    

あなたは機能的なスタイルを採用しようとしている場合は、変更可能な値を避けるようにしてくださいます。

このような例を示します。

let nr =
   let rec compute nr =  
      if checkMod nr then nr else compute (nr + 20)
   compute 0     

while表現 F#であなたが命令型言語から来ている場合に慣れる少しを取ります。 while式の各行は(C ++ / C#のからunitを考える)voidで評価する必要があります。全体的な表現は、その後もunitに評価されます。

の例で

nr <- nr + 20

一方unitに評価
f = checkMod nr
Noldorin のが述べたように、

boolに評価されます。警告メッセージでこの結果が報告されています。あなたがそう望む場合には、実際に警告をオフにすることができます。ちょうどあなたのファイルの先頭に以下を入れます:

#nowarn "0020"

私は長い時間のために不可欠なスタイルでプログラミングをしてきたので、関数型プログラミングの考え方に慣れるには時間がかかりました。

あなたの例では、あなたのcheckModテストに合格する20の最初の倍数を見つけるためにしようとしています。それは、のものをの部分です。機能の方法の部分については、私は、配列に利用可能な方法を通じてブラウジングをお勧めします。何が必要このように、あなたのテストに合格(20の倍数)シーケンスの最初の要素です。

let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod

最初のletがtwentyplesの無限のリストを(私は1つを作った)を発生します。二letがあなたのテストに合格すると、リスト内の最初の番号を見つけました。あなたの仕事は、実際の試験に合格する数があることを確認することですが、それは不可欠のコードのためにも、もちろん事実です。

あなたは1に2本の以上のラインを凝縮したい場合は、また書くことができます。

let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod

私は数週間後、それを読み取ろうとする際に、コードにそのようなスタントを引っ張っすると頭痛につながることがわかります。

ブライアンのポストと同じ精神で、ここに警告FS0020を取得する別の方法です:。一言で言えば、私は誤って、関数の引数をtupled

文字列(この式は、」タイプ「ユニット」を持っている必要がありますが、入力した:

のF#の初心者なので、私は2番目の行(GDPを聞かせて...)のための警告FS0020を与えた、困難な時期以下のコードをデバッグしていました - > ^ - >単位)*文字列*フロート」。これは、その行は全く問題ではなかったが判明しました。その代わり、それが台無しにされたprintfnラインでした。引数リストからカンマ区切り文字を削除すると、それを修正します。

for country in wb.Regions.``Arab World``.Countries do
  let gdp = country.Indicators.``GDP per capita (current US$)``.[2010]
  let gdpThous = gdp / 1.0e3
  printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top