4

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?

Luka Horvat
  • 4,283
  • 3
  • 30
  • 48
  • Related post - [Shadowing and Nested function](https://stackoverflow.com/q/2478079/465053) – RBT May 15 '18 at 23:14

2 Answers2

7

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

Community
  • 1
  • 1
ildjarn
  • 62,044
  • 9
  • 127
  • 211
1

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.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Fyodor Soikin
  • 78,590
  • 9
  • 125
  • 172