tags:

views:

201

answers:

4

Does every function has to be inside a type like in C#? Or does F# has free functions?

Also what about functions I have seen all over some F# code like, cos, sin, etc. Are they calls to Math.Cos, Math.Sin?

Also why did they provide cos, sin, etc like that instead of Math.Cos, Math.Sin?

+7  A: 

F# can have functions scoped in modules (instead of classes).

The CLR implements these, internally, as:

as a common language runtime (CLR) class that has only static members

They look like "free functions" within the scope of a module.

Reed Copsey
Thanks Reed. Do you know why they chose to do that for math functions. Or you mean there is no type.method in F#? Everything is function (object)?
Joan Venge
@Joan: F# has a *long* heritage. Those stuff are inherited from OCaml. F# does have method calls like C# too.
Mehrdad Afshari
Thanks Mehrdad. Last question: why is CLR is configured so it can't have true free functions but has to fake it with a static class? Just wondering.
Joan Venge
CLR actually has support for free functions. Not sure why F# compiler is "faking" them - probably to implement modules.
Nemanja Trifunovic
@Nemanja Trifunovic: Do you have a reference showing the CLR's "free function" support? My understanding is that the CLR does not have support for this, and requires "free functions" to be wrapped into a static class in the CLR.
Reed Copsey
@Reed - The CLR allows "global" static methods to be placed on the special top-level `<Module>` type, which is a type defined in each module which has no base class and which has special rules for metadata merging.
kvb
+6  A: 

As Reed mentioned, functions can be defined within modules a la other ML languages, but they can also be defined on types like other .NET languages (and in fact modules are also compiled to classes). Within F#, modules can be opened to access the functions without having to use the module name each time, and modules are automatically created on a per-file basis if they aren't explicitly declared.

As to why there are separate cos, etc. functions instead of merely relying on .NET's built-in Math.Cos, etc., there are probably several reasons:

  1. Uniformity: cos looks much more idiomatic in F# than calling the static method System.Math.Cos.
  2. Static constraints: cos doesn't just work on floats in F#, it also works on float32s and on any type which exposes a static Cos method, so you can create your own types to which the cos function can be applied.

I'd guess that truly free functions aren't allowed because there are many .NET languages which don't expose convenient access to them, so using them would present a barrier to cross-language interoperability. The CLR itself does support free functions, and some languages such as C++/CLI do use them, but most languages compile functions into classes (even if that's not how it looks from a source code perspective, as in F#).

kvb
Another reason is that `cos` can be implemented with F#-style arguments rather than tupled arguments, allowing for partial function application, which `Math.Cos` doesn't support.
Joel Mueller
@Joel - can you expand on what you mean? Like all one-argument .NET functions, `System.Math.Cos` can be used as an `_ -> _`, just like `cos`. If it took multiple arguments, then you would be correct.
kvb
Thanks kvb. So F# cos is another method other than Math.Cos? Where is the full name for F# cos then? CommonInvisibleStaticClass.Cos? Or the cos has been defined for everything in F# like you said.
Joan Venge
@Joan - it's in the Microsoft.FSharp.Core.Operators module, which is opened by default (so that all functions within it can be accessed without having to qualify them with the module name). See http://msdn.microsoft.com/en-us/library/ee353754%28VS.100%29.aspx and http://msdn.microsoft.com/en-us/library/ee340316%28VS.100%29.aspx.
kvb
@kvb - Cos was a bad example - I wasn't paying attention to the actual method. Generally speaking, if there is more than one parameter, I would rather use a `max` with a signature of `int -> int -> int` than `Math.Max` with a signature of `(int * int) -> int`. As one more reason to make functional aliases for things that are already built into the framework.
Joel Mueller
+4  A: 

@Reed's answer is good. I just wanted to add that in F# you can 'open' modules so that module-bound functions can be called in an unqualified way, and that is where various 'top level' functions and operators come from, e.g.

http://msdn.microsoft.com/en-us/library/ee353754(VS.100).aspx

That is, F# is still subject to the CLR mechanisms, which means that every function must be in a class, but F# modules map to static classes on the CLR, modules can be 'opened' to provide the functions at the top level, and a handful of modules are 'auto-opened' so that the most common/convenient functions are available right away.

Having a variety of common functions available is very useful for scripting or interactive sessions, where you don't want to have to open a bunch of namespaces or spell out in 15 characters "System.Math.Cos" just to compute a cosine.

Brian
Thanks so I am right to assume this can only be applied to static functions? Like you can't open instance functions to be top level free functions, right?
Joan Venge
Yes, it can only be applied to functions in modules (which happen to be static).
Brian
+3  A: 

Joan,

Rather than all these questions about which features F# supports or does not support, maybe you'd be better served to start with a book on F#. Consider these two resources as a starting point:

http://en.wikibooks.org/wiki/F_Sharp_Programming

And also:

The F# Survival Guide

There's also Chris Smith's book which is an excellent introductory text.

Programming F#

Maybe you want to read them and work through them and then you can ask more directed questions. Just an idea.

Onorio Catenacci