Here I am attempting to use an imperative style factorial function, but despite the last line of the function declaring a ref
to be returned, fsc is telling me that the function is returning a unit. I know mutables are not allowed to be returned, but I thought you could circumvent that by using a ref
? Also, please do not tell me to rewrite it in a functional way. I know that is an alternative, but I am trying to get a better understanding of how imperative programming works in the language.
Here is my program:
let factorial n = do
let res = ref 1
for i = 2 to n do
res := !res * i
res
[<EntryPoint>]
let main(args : string[]) =
let result = factorial 10
printfn "%d" !result
This is what the compiler gives me:
factorial.fs(2,5): warning FS0020: This expression should have type 'unit', but
has type 'int ref'. Use 'ignore' to discard the result of the expression,
or 'let' to bind the result to a name.
factorial.fs(10,13): error FS0001: Type mismatch. Expecting a
'a -> int
but given a
'a -> unit
The type 'int' does not match the type 'unit'
factorial.fs(10,19): error FS0001: This expression was expected to have type
'a ref
but here has type
unit
All you need to do is remove do
, do
used in this context is specifically for performing side-effects, hence the expected return type of unit.
Also, your function is not correct, you need to replace n
with i
in the loop.
let factorial n =
let res = ref 1
for i = 2 to n do
res := !res * i
res
By the way, you don't need to use references, you can just write it like this:
let factorial n =
let mutable res = 1
for i = 2 to n do
res <- res * i
res