F#错误:表达式预计有类型单元
我想在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()
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()
**添加1 ** |> +1 – Funk
请张贴[最小,完整的,并且可验证示例](http://stackoverflow.com/help/mcve)。 –
模式匹配的所有返回值必须是相同的类型。 如果匹配'scientificInput',则所有函数都会返回'float', 除了'printfn',它返回'unit'。 – Funk
Thanks @ Funk ...你可以给我一个关于我如何做这项工作的想法。按6之后,我想要显示科学菜单 –