F#:警告 FS0020:この式のタイプは「unit」である必要がありますが、タイプは「bool」です。
質問
オイラー問題をいくつか解いて 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
私は長い時間のために不可欠なスタイルでプログラミングをしてきたので、関数型プログラミングの考え方に慣れるには時間がかかりました。
あなたの例では、あなたの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