Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Name Tuples/Anonymous Types in F#?

Tags:

c#

f#

in C# you can do stuff like :

var a = new {name = "cow", sound = "moooo", omg = "wtfbbq"}; 

and in Python you can do stuff like

a = t(name = "cow", sound = "moooo", omg = "wtfbbq") 

Not by default, of course, but it's trivial to implement a class t that lets you do it. Infact I did exactly that when I was working with Python and found it incredibly handy for small throwaway containers where you want to be able to access the components by name rather than by index (which is easy to mix up).

Other than that detail, they are basically identical to tuples in the niche they serve.

In particular, I'm looking at this C# code now:

routes.MapRoute(             "Default", // Route name             "{controller}/{action}/{id}", // URL with parameters             new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults         ); 

and it's F# equivalent

type Route = {      controller : string     action : string     id : UrlParameter }  routes.MapRoute(     "Default", // Route name     "{controller}/{action}/{id}", // URL with parameters     { controller = "Home"; action = "Index"; id = UrlParameter.Optional } // Parameter defaults   ) 

Which is both verbose and repetitive, not to mention rather annoying. How close can you get to this sort of syntax in F#? I don't mind jumping through some hoops (even flaming hoops!) now if it means it'll give me something useful to DRY up code like this.

like image 490
Li Haoyi Avatar asked Nov 15 '11 22:11

Li Haoyi


People also ask

What is the difference between tuples and anonymous types *?

The ValueTuple types are mutable, whereas Tuple are read-only. Anonymous types can be used in expression trees, while tuples cannot.

What are anonymous data types?

Anonymous types are class types that derive directly from object , and that cannot be cast to any type except object . The compiler provides a name for each anonymous type, although your application cannot access it.

What is anonymous type of functions?

Definition. Anonymous type, as the name suggests is a type that doesn't have any name. Anonymous types are the new concept in C#3.0 that allow us to create new type without defining them. This is a way to define read only properties into a single object without having to define type explicitly.

Are tuples reference types?

Tuple types are reference types. System. ValueTuple types are mutable.


2 Answers

I find it easier to do

let route = routes.MapRoute(     "Default", // Route name     "{controller}/{action}/{id}" // URL with parameters     ) route.Defaults.Add("controller", "Home") route.Defaults.Add("action", "Index") 

or

[ "controller", "Home"   "action", "Index" ] |> List.iter route.Defaults.Add 

In F#, I would avoid calling overloads that accept anonymous types much as I would avoid calling an F# method accepting FSharpList from C#. Those are language-specific features. Usually there is a language-agnostic overload/workaround available.

EDIT

Just looked at the docs--here's yet another way to do it

let inline (=>) a b = a, box b  let defaults = dict [   "controller" => "Home"   "action"     => "Index"  ] route.Defaults <- RouteValueDictionary(defaults) 
like image 99
Daniel Avatar answered Oct 03 '22 21:10

Daniel


You can't create "anonymous records" in F# - when using types, you can either use tuples which are anonymous, but don't carry labels or you can use records which have to be declared in advance and have labels:

// Creating an anonymous tuple let route = ("Home", "Index", UrlParameter.Optional)  // Declaration and creating of a record with named fields type Route = { controller : string; action : string; id : UrlParameter }  let route = { controller = "Home"; action = "Index"; id = UrlParameter.Optional }  

Technically, the problem with anonymous records is that they would have to be defined as actual classes somewhere (the .NET runtime needs a type), but if the compiler put them in every assembly, then two anonymous records with same members might be different types if they were defined in different assemblies.

Honestly, I think that the example you posted is just a poor design decision in ASP.NET - it is misusing a particular C# feature to do something for which it wasn't designed. It may not be as bad as this, but it's still odd. The library takes a C# anonymous type, but it uses it as a dictionary (i.e. it uses it just as a nice way to create key-value pairs, because the properties that you need to specify are dynamic).

So, if you're using ASP.NET from F#, it is probably easier to use an alternative approach where you don't have to create records - if the ASP.NET API provides some alternative (As Daniel shows, there is a nicer way to write that).

like image 32
Tomas Petricek Avatar answered Oct 03 '22 21:10

Tomas Petricek