2016-11-11 44 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

相关问题