F# error: expression was expected to have type unit
F# error: expression was expected to have type unit
我正在尝试用 F# 构建一个计算器。因此,我从用户那里获取有关要执行的操作的输入。对于输入 6,它应该显示科学操作的菜单,但是,它说表达式应该具有单位类型但具有浮点型。同样在 scientificFun() 函数中,最后一行是 'The expression was expected to have float but here has unit'。我不确定这是什么意思。坚持了几个小时。任何帮助,将不胜感激。谢谢!。 ** 或粗线表示发生错误的位置。
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 并将 returns 作为字符串。所以,这行得通: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)
。这是一个不接受输入(单位)和 returns 浮点数的函数。但是在选项 _ 中,您有 _ -> printfn("Choose between 1 - 9")
。 printfn
打印到控制台,而不是 return 一个值,或者更确切地说它是 returns () (unit),这表明它有一个副作用,好吧, 打印到控制台。你不能 return 一个分支的浮点数和另一个分支的其他东西。有几种方法可以解决这个问题,其中一种方法是由@Funk 建议的,基本上将 return 值包装在 Option 类型中,这可能是最好的选择;^)。但是在这种情况下,让我们稍微作弊,并以一种快速而肮脏的方式修复您的功能:
将匹配表达式的最后一行更改为:
| _ -> printfn("Choose between 1 - 9");0.
这里的通配符变成了一个复合表达式,打印出来,但最后 returns 0.,这是一个浮点数,F# 编译器很高兴。
那么你还需要在最后一场比赛中修正选项6。如果你看上面,你可以看到所有其他分支都打印到控制台,return 单元也应该如此,但是 scientificFun 的签名会告诉你它 returns float,那么它是哪个?只需将分支更改为看起来像所有其他表达式:
| "6" -> printfn("The Result is: %f") <| scientificFun()
一旦你完成了这项工作,我建议你可能 post 把它放到 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()
我正在尝试用 F# 构建一个计算器。因此,我从用户那里获取有关要执行的操作的输入。对于输入 6,它应该显示科学操作的菜单,但是,它说表达式应该具有单位类型但具有浮点型。同样在 scientificFun() 函数中,最后一行是 'The expression was expected to have float but here has unit'。我不确定这是什么意思。坚持了几个小时。任何帮助,将不胜感激。谢谢!。 ** 或粗线表示发生错误的位置。
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 并将 returns 作为字符串。所以,这行得通: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)
。这是一个不接受输入(单位)和 returns 浮点数的函数。但是在选项 _ 中,您有 _ -> printfn("Choose between 1 - 9")
。 printfn
打印到控制台,而不是 return 一个值,或者更确切地说它是 returns () (unit),这表明它有一个副作用,好吧, 打印到控制台。你不能 return 一个分支的浮点数和另一个分支的其他东西。有几种方法可以解决这个问题,其中一种方法是由@Funk 建议的,基本上将 return 值包装在 Option 类型中,这可能是最好的选择;^)。但是在这种情况下,让我们稍微作弊,并以一种快速而肮脏的方式修复您的功能:
将匹配表达式的最后一行更改为:
| _ -> printfn("Choose between 1 - 9");0.
这里的通配符变成了一个复合表达式,打印出来,但最后 returns 0.,这是一个浮点数,F# 编译器很高兴。
那么你还需要在最后一场比赛中修正选项6。如果你看上面,你可以看到所有其他分支都打印到控制台,return 单元也应该如此,但是 scientificFun 的签名会告诉你它 returns float,那么它是哪个?只需将分支更改为看起来像所有其他表达式:
| "6" -> printfn("The Result is: %f") <| scientificFun()
一旦你完成了这项工作,我建议你可能 post 把它放到 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()