Search code examples
f#return-typerefimperative

Function returning type unit instead of type ref


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

Solution

  • 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