2016-11-11 2 views
1

저는 F #으로 계산기를 만들려고합니다. 그래서 나는 수행 할 작업과 관련하여 사용자로부터 의견을받습니다. 입력 6의 경우 과학적 조작을위한 메뉴가 표시되어야하지만 표현식에는 유형 단위가 있어야하지만 유형은 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'과 일치하는 곳에서는 모든 함수가'unit '을 반환하는'printfn'을 제외하고'float', 을 반환합니다. – Funk

+0

Thanks @ Funk .. 내가 어떻게이 일을 할 수 있는지에 대한 아이디어를 줄 수 있니?. 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은 콘솔에 인쇄하고 값을 반환하지 않으며, 오히려 콘솔에 부작용이 있음을 나타내는() (단위)를 반환합니다. 한 지점에서 플로트를, 다른 지점에서 플로트를 반환 할 수 없습니다. 이 문제를 해결하는 방법은 여러 가지가 있습니다. 그 중 하나는 @Funk에 의해 제안되었지만, 기본적으로 리턴 값을 옵션 유형으로 감싸는 것이 가장 좋은 옵션입니다 (^^).

변경이에 대한 일치 식의 마지막 행 :하지만이 경우의 조금 속임수, 그리고 신속하고 더러운 방법으로 함수를 수정하자 여기 | _ -> printfn("Choose between 1 - 9");0. 와일드 카드가 복합 표현되고, 인쇄하는, 마지막으로 float 인 0을 반환하고 F # 컴파일러가 만족 스럽습니다.

그런 다음 마지막 경기에서 옵션 6을 수정해야합니다. 위에서 보았을 때 다른 모든 브랜치가 콘솔로 출력된다는 것을 알 수 있으므로 unit을 반환해야하지만 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

관련 문제