Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate definition of type or module when defining a type and a module with the same name

Tags:

f#

So as far as I understand, the convention is to define your type, and then define a module with the same name after it with the functions that operate on the type.

I'm trying to do that so I have this code

namespace Rand

type ImmutableRandom

module ImmutableRandom =
    open System

    val fromSeed : int -> ImmutableRandom
    val int : ImmutableRandom -> int
    val intInRange : ImmutableRandom -> int -> int -> int
    val double : ImmutableRandom -> double
    val next : ImmutableRandom -> ImmutableRandom

I'm getting the error that ImmutableRandom (the name of the module is underlined) is redefining a type or a module.

In the very same project, the identical setup works for a different type, with the only difference being that that type has a generic parameter, while ImmutableRandom doesn't.

What am I doing wrong?

like image 882
Luka Horvat Avatar asked Feb 11 '23 12:02

Luka Horvat


2 Answers

Use the CompilationRepresentation attribute on your module so that it has the same name in source, but not in IL:

namespace Rand

type ImmutableRandom

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module ImmutableRandom =
    open System

    val fromSeed : int -> ImmutableRandom
    val int : ImmutableRandom -> int
    val intInRange : ImmutableRandom -> int -> int -> int
    val double : ImmutableRandom -> double
    val next : ImmutableRandom -> ImmutableRandom

This will cause the module to be named ImmutableRandomModule in IL (and consequently from languages other than F#). This has a few advantages over static members, which are well summarized in this answer: F# code organization: types & modules

like image 196
ildjarn Avatar answered Feb 13 '23 02:02

ildjarn


This works if the type is generic. Otherwise, there is ambiguity that the compiler cannot resolve on its own.

If you really feel the need to do this with a non-generic type, define all the functions as static members on the type. A bit less elegant, but you get the same surface API.

like image 37
Fyodor Soikin Avatar answered Feb 13 '23 02:02

Fyodor Soikin