views:

100

answers:

2

I have a discriminated union that I want to use as an argument for a function I'm exposing in a signature file. Currently I have the code defined as such:

Signature.fsi:

type Union =
| Part of string
| Part2 of int

val Func: Union -> unit

With Func being defined in a seperate fs file.

The problem is when I do this the fs file can't pick up the Union definition so code that creates a Part or Part2 value fails. Unless I define the union again in the fs file that is using the union.

So for example:

Signature.fs:

type Union =
| Part of string
| Part2 of int

let Func input:Union =
    ignore

OtherFile.fs

type Union =
| Part of string
| Part2 of int

let DoSomething =
    Func(Part("Test"))

Without redefining Union every time this fails. Have I missed something obvious? I'm still fairly green when it comes to F#.

+1  A: 

Your f# project needs to order the files in the correct order. This means placing the file containing the definition of Func higher up (literally) than the files using it. You may want to consider placing such defenitions in fsi files instead.

I would point out that using the type name Func is a really bad idea given the prevalence (and assumption by most users) that Func means the 3.5 standard (* -> x) delegates.

ShuggyCoUk
Well, using Union for a union would probably be a bad idea! They're just placeholders for the sake of the question.
Massif
Ah right, I'm a Foo Bar Baz kinda guy myself :)Does re-ordering fix your problem?
ShuggyCoUk
A combination of file order and what Princess said has got me going. I'm still annoyed at having to define the type in more places than just the signature file though.
Massif
+4  A: 

I think you're looking for something like this:

Test.fsi:

#light

type Union =
    | Part of string
    | Part2 of int

val awesome: Union -> unit

Test.fs:

#light

type Union =
    | Part of string
    | Part2 of int

let awesome (x :Union) = printfn "%A" x

This creates a module called Test which you can access from other files:

AnotherTest.fs:

#light

let wickedAwesome() =
    Test.awesome(Test.Part("hellz yeah!"))

If you open the Test module, you can re-write AnotherTest.fs as follows:

#light
open Test

let wickedAwesome() =
    awesome (Part("hellz yeah!"))

See F# Modules and Namespaces for a more thorough tutorial.

Juliet
this is what I've ended up with... I'm just kinda annoyed I have to define the type twice, once in the signature and once in the rest of the module... I'm hoping this gets changed at some point.
Massif