2016-11-11 80 views
1

我想在F#中構建一個計算器。所以,我從用戶那裏獲得關於要執行的操作的輸入。對於輸入6,它應該顯示科學操作的菜單,但是,它表示表達式預期具有類型單位,但是具有浮點類型。並且在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',則所有函數都會返回'float', 除了'printfn',它返回'unit'。 – Funk

+0

Thanks @ Funk ...你可以給我一個關於我如何做這項工作的想法。按6之後,我想要顯示科學菜單 –

回答

3

The expression was expected to have float but here has unit

這是編譯器一個非常重要的消息,你應該試着理解爲什麼它是這麼說的,這意味着什麼。在非常簡單的術語中,函數將值從一個域映射到另一個域。

如果你有一個函數,例如:

let makeStr (x:int) = 
    string x 

其簽名會告訴你什麼是它的輸入和輸出類型:val makeStr : x:int -> string。在這種情況下,它接受一個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)。這是一個不輸入(單位)並返回一個浮點數的函數。然而在選擇_中,您有_ -> printfn("Choose between 1 - 9")printfn打印到控制檯,並且不返回一個值,或者更確切地說它返回()(單位),這表明它有一個副作用,打印到控制檯。你不能從一個分支返回一個浮動,而從另一個分支返回其他東西。有幾種方法可以解決這個問題,@Funk提出了其中的一種方法,基本上把你的返回值封裝在一個Option類型中,這可能是最好的選擇; ^)。但是,在這種情況下,讓我們欺騙了一下,在一個快速和骯髒的方式解決了你的函數:

更改比賽表達的最後一行是: | _ -> printfn("Choose between 1 - 9");0. 這個通配符成爲一個複合式,即印刷,但最終返回0.,這是一個浮點數,並且F#編譯器很高興。

然後你仍然需要在最後的比賽中修復選項6。如果你看上面你可以看到所有其他分支都打印到控制檯上,所以應該返回單元,但是ScientificFun的簽名會告訴你它返回浮動狀態,所以它是哪一個?只要改變分支看起來像所有其他表達式: | "6" -> printfn("The Result is: %f") <| scientificFun()

一旦你得到了這個工作,我建議,也許你張貼此到CodeReview它可以用更地道F#/實用的風格進行返工。

而且這些引用可以幫助你前進的道路:

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

相關問題