Difference between `let f = fun a -> a-1` and `let f a = a-1` in F#

后端 未结 3 1649
北海茫月
北海茫月 2021-01-13 00:21

In F#, is there any difference whatsoever between let f = fun a -> a-1 and let f a = a-1? As far as I can see, the latter is simply syntactic s

3条回答
  •  走了就别回头了
    2021-01-13 00:43

    As others already mentioned, the simple answer is that defining a function using let foo x = ... and using let foo = ... can give you different results (because of value restriction), but it does not happen in this case, because the compiler is smart enough to know that it can safely treat let foo = fun x -> .. as let foo x = ....

    Now, if you want to see more details, try the following definitions:

    let f a = a              // Function 'a -> 'a
    let g = fun a -> a       // Function 'a -> 'a 
    let h = (); fun a -> a   // error FS0030: Value restriction
    

    So, the compiler treats a function defined using let foo = fun x -> ... as an ordinary function as long as there is nothing else before the code that creates & returns the function. If you do anything beofore that (even if it's just ignoring the unit value), then there is a difference.

    If you want to learn more, then the section 14.6.7 Generalization in the F# 3.0 specification lists all generalizable values (that is, the expressions for which the above works):

    The following expressions are generalizable:

    • A function expression
    • An object expression that implements an interface
    • A delegate expression
    • A “let” definition expression in which both the right-hand side of the definition and the body of the expression are generalizable
    • A “let rec” definition expression in which the right-hand sides of all the definitions and the body of the expression are generalizable
    • A tuple expression, all of whose elements are generalizable 
    • A record expression, all of whose elements are generalizable, where the record contains no mutable fields 
    • A union case expression, all of whose arguments are generalizable
    • An exception expression, all of whose arguments are generalizable
    • An empty array expression 
    • A constant expression
    • An application of a type function that has the GeneralizableValue attribute.

    The important thing is the first point - that a function expression (e.g. fun x -> x) is generalizable; A sequencing expression (e.g. (); fun x -> x) is not generalizable and so it behaves differently than a plain function.

提交回复
热议问题