Reputation: 463
I'm trying to make a simple factorial function in F# that uses a value inputted from the user (using the console, I don't know if that makes any difference) but I can't seem to find any solution to be able to use the value from the user in my function.
open System
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
let input = Console.ReadLine()
Console.WriteLine(fact input)
It constantly gives me the error saying "This expression was expected to have type "int" but here has type "string"". If anyone has any idea on how to make it work properly (or at least can tell me what I need to do to convert my user inputted value into an INT, that would be greatly appreciated.
Upvotes: 5
Views: 1765
Reputation: 667
My advice would be to try to use F# functions unless there isn't an equivalent F# function.
Second of all, the type cast functions in F# have System.(type).(Try)Parse
embedded in them. "Try
" here is optional, and type
is any number type like int8
, ..., int64
, float32
and float. (last one are 64 bit)
So int "123" = System.Int32.Parse("123")
is true. The two functions are equivalent. This goes for floating point numbers too.
Third, if you can, try to use tail recursion:
let fact n =
let rec help acc = function
| n when n <= 0 -> acc
| n -> help (acc*n) (n-1)
help 1 n
let input = System.Console.ReadLine()
printfn "fact %s = %d" input (fact (int input))
If we type 4
and then press enter, the output would be:
fact 4 = 24
I don't know if there is any equivalent to ReadLine
in F#. I couldn't find any.
The reason to try to stick to the F# style and not jump around between C# and F# is that other readers and yourself might get confused because it might make the code less readable.
Upvotes: 0
Reputation: 39320
Since both:
somevalue |> int
and
System.Int32.Parse somevalue
Throw an exception on invalid input is it not better to prevent your app from blowing up at runtime?
Since I could not find any function that returns int option
I wrote one:
let asInt32 numberString =
let (success,num) =
System.Int32.TryParse(numberString)
if success then
Some num
else
None
asInt32 "22"
(using TryParse as Gustavo suggested)
Upvotes: 4
Reputation: 26194
F# does no automatic conversions for you, so you'll need to parse the string:
open System
let rec fact x =
if x < 1 then 1
else x * fact (x - 1)
let input = Console.ReadLine()
Console.WriteLine(fact (Int32.Parse input))
In theory you would need to convert back to string to print it, but it works because there is an overload for Console.WriteLine that takes an integer and does the conversion.
Upvotes: 3