2016-11-11 15 views
1

私はF#で電卓を作ろうとしています。だから、私は実行される操作に関するユーザーからの入力を受け取ります。入力6では科学的操作のメニューが表示されるはずですが、expressionには型ユニットがあると予想され、float型があります。また、scientificFun()関数では、最後の行については、 '式は浮動小数点になると予想されていましたが、ここには単位があります。私はそれが何を意味するか分からない。これに何時間もぶつかった。どんな助けもありがとう。ありがとう! **または太字の行は、エラーが発生している場所を示しています。F#エラー:式が型ユニットを持つと予想されました

open System 

let mutable ok = true 
while ok do 
Console.WriteLine("Choose a operation:\n1.Addition\n2.Substraction\n3.Multiplication\n4.Division\n5.Modulo\n6.Scientific") 
let input= Console.ReadLine() 

let add() = 
    Console.WriteLine("Ok, how many numbers?") 
    let mutable count = int32(Console.ReadLine()) 
    let numberArray = Array.create count 0.0 
    for i in 0 .. numberArray.Length - 1 do 
     let no = float(Console.ReadLine()) 
     Array.set numberArray i no  
    Array.sum numberArray 

let expo() = 
    Console.WriteLine("Enter the base") 
    let getBase = Console.ReadLine() 
    Console.WriteLine("Enter the exponent") 
    let getExponent = Console.ReadLine() 
    float(getBase) ** float(getExponent) 

let sqRoot() = 
    Console.WriteLine("Enter a number") 
    let no = float(Console.ReadLine())   
    Math.Sqrt no 

let rec fact (n:float) = 
    if n < 1.0 then 1.0 
    else n * fact (n - 1.0) 

let factorial() = 
    Console.WriteLine("Enter a number") 
    let no = float(Console.ReadLine()) 
    fact(no) 


let Trigsin() = 
    Console.WriteLine("Enter an angle") 
    let angle = float(Console.ReadLine()) 
    Math.Sin angle 
let Trigcos() = 
    Console.WriteLine("Enter an angle") 
    let angle = float(Console.ReadLine()) 
    Math.Cos angle 
let Trigtan() = 
    Console.WriteLine("Enter an angle") 
    let angle = float(Console.ReadLine()) 
    Math.Tan angle 

let logicalAnd() = 
    Console.WriteLine("Enter first number") 
    let first = int32(Console.ReadLine()) 
    Console.WriteLine("Enter second number") 
    let second = int32(Console.ReadLine()) 
    float(first &&& second) 
let logicalOr() = 
    Console.WriteLine("Enter first number") 
    let first = int(Console.ReadLine()) 
    Console.WriteLine("Enter second number") 
    let second = int(Console.ReadLine()) 
    float(first ||| second) 
let logicalNot()= 
    Console.WriteLine("Enter a number") 
    let first = int32(Console.ReadLine()) 
    float(~~~first) 
let sub x y = x - y 
let mul x y = x * y 
let div x y = x/y 
let MOD x y = x % y 

let scientificFun() = 
    printfn("1.Exponential\n2.Square Root\n3.Factorial\n4.sin()\n5.cos()\n6.tan()\n7.AND\n8.OR\n9.NOT") 
    let scientificInput = Console.ReadLine() 
    match scientificInput with 
    |"1" -> expo() 
    |"2" -> sqRoot() 
    |"3" -> factorial() 
    |"4" -> Trigsin() 
    |"5" -> Trigcos() 
    |"6" -> Trigtan() 
    |"7" -> logicalAnd() 
    |"8" -> logicalOr() 
    |"9" -> logicalNot() 
    | _ -> **printfn("Choose between 1 - 9")** 



match input with 
| "1" -> printfn("The Result is: %f") (add()) 
//| "2" -> printfn("The Result is: %f") (sub A B) 
//| "3" -> printfn("The Result is: %f") (mul A B) 
///| "4" -> printfn("The Result is: %f") (div A B) 
//| "5" -> printfn("The Result is: %f") (MOD A B) 
| "6" -> **scientificFun()** 
| _-> printfn("Choose between 1 and 6") 
Console.WriteLine("Would you like to use the calculator again? y/n") 
let ans = Console.ReadLine() 
if ans = "n" then 
    ok <- false 
else Console.Clear() 
+2

[最小限で完全であり、検証可能な例](http://stackoverflow.com/help/mcve)を投稿してください。 –

+2

パターンマッチのすべての戻り値は同じ型でなければなりません。 'scientificInput'にマッチしたところでは、' print'の 'units'を除いて、すべての関数が' float'を返します。 を除きます。 – Funk

+0

おかげさまで@ファンク。私はこの仕事をどうやって作れるのか考えてくれますか? 6を押すと、科学メニューが表示されます。 –

答えて

3

The expression was expected to have float but here has unit

これは、コンパイラからの非常に重要なメッセージであり、あなたはそれがそう言う理由を理解してみてください、とそれが意味する必要があります。非常に簡単に言えば、関数は値をあるドメインから別のドメインにマップします。

あなたが例えば機能を持っている場合:val makeStr : x:int -> string

let makeStr (x:int) = 
    string x 

その署名がその入力と出力の種類が何であるかを教えてくれます。この場合、intをとり、文字列として返します。だから、これは動作します:makeStr 10が、これは、それが次のメッセージで失敗しますないmakeStr 10.ます

error FS0001: This expression was expected to have type int but here has type float

をあなたの特定のケースでは、あなたがscientificFun()の署名を確認することができます。 VSCodeとVS2015の両方で、それがval scientificFun : (unit -> float)であることがわかります。これは、入力(単位)を取らずにfloatを返す関数です。しかし選択_では、あなたは_ -> printfn("Choose between 1 - 9")です。 printfnはコンソールに出力し、値を返さず、むしろコンソールに印刷する副作用があることを示す()(単位)を返します。あるブランチからフロートを返し、別のブランチから何かを戻すことはできません。これを回避するにはいくつかの方法がありますが、そのうちの1つは@Funkによって提案されたものですが、基本的にOptionオプションで戻り値をラップします。しかし、このケースでのビットをカンニング、迅速かつ汚い方法であなたの機能を修正してみましょう:

変更し、これに一致式の最後の行:ここ | _ -> printfn("Choose between 1 - 9");0. は、ワイルドカードを印刷すること、複合式となり、最終的に浮動小数点である0を返し、F#コンパイラは満足しています。

最後に、オプション6を修正する必要があります。上記を参照すると、他のすべてのブランチがコンソールに印刷されていることが分かります。ユニットを返す必要がありますが、scientificFunのシグネチャはフロートを返します。ただ、他のすべての表現のように見えるように枝を変更する:あなたは、この作業を得たら | "6" -> printfn("The Result is: %f") <| scientificFun()

私は多分あなたはそれがより多くの慣用的なF#/機能的なスタイルで再加工することができCodeReviewにこれを投稿することを示唆しています。

また、これらの文献は、道に沿ってあなたを助ける必要があります。

Match Expressions
Pattern Matching
Match Expressions 2
F# Expressions and Syntax
Thinking Functionally

を追加1

ScientificFun()自体を呼び出す再帰関数にすることもできます。

let rec scientificFun() = 
    printfn("1.Exponential\n2.Square Root\n3.Factorial\n4.sin()\n5.cos()\n6.tan()\n7.AND\n8.OR\n9.NOT") 
    let scientificInput = Console.ReadLine() 
    match scientificInput with 
    |"1" -> expo() 
    |"2" -> sqRoot() 
    |"3" -> factorial() 
    |"4" -> Trigsin() 
    |"5" -> Trigcos() 
    |"6" -> Trigtan() 
    |"7" -> logicalAnd() 
    |"8" -> logicalOr() 
    |"9" -> logicalNot() 
    | _ -> scientificFun() 
+0

** 1 ** |> +1を追加 – Funk

関連する問題