Our journey to F#: CompilationRepresentationAttribute

We have a solution containing C# and F# code. In this post, I’ll show you how the CompilationRepresentationAttribute helps to use F# code from C# by preventing naming conflicts on types and modules.

In our F# code, we have a module that “extends” the type Task with some useful functions:

[<RequireQualifiedAccess>]
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Task =

    open System.Threading.Tasks


    let Ignore (t : Task<_>) =
        task {
            let! _ = t
            ()
        }


    let map (f : 'a -> 'b) (t : Task<'a>) =
        task {
            let! a = t
            return f a
        }


    let fromOption (taskOption : Task<_> option) =
        task {
            match taskOption with
            | Some t ->
                let! value = t
                return Some value
            | None -> return None
        }

The task computation expression is from the library Ply.

The module uses the CompilationRepresentation attribute with the argument CompilationRepresentationFlags.ModuleSuffix so that the module is seen by C# as TaskModule, and not as Task, which would be the default.

F# allows having types and modules with shared names – even with multiple modules. C# does not.

Using the attribute eliminates the conflict between our Task module and the type Task from the System namespace. Without the attribute, we would always have to fully qualify at least one of them, when we need both in a class.

That’s all for today! Happy coding.

F# code can still use the module with e.g. Task.Ignore.

This blog post is made possible with the support of Time Rocket, the product this journey is all about. Take a look (German only).

Find all blog posts about our journey to F# here.

About the author

Urs Enzler

Add comment

By Urs Enzler

Recent Posts