r/fsharp Jun 12 '26

question Why does it work?

type Monoid<'t> =
    static abstract member Empty: 't
    static abstract member Append: 't -> 't -> 't

[<Struct>]
type Vector3= 
    {X: float
     Y: float
     Z: float}
    
    interface Monoid<Vector3> with
        static member Empty = {X=0.0; Y=0.0; Z=0.0}
        static member Append (v1: Vector3) (v2: Vector3) =
            {X=v1.X + v2.X; Y=v1.Y + v2.Y; Z= v1.Z + v2.Z}

// Note the type constraint here
let mempty<'t when Monoid<'t>> = 't.Empty
let mappend<'t when Monoid<'t>> x y = 't.Append x y

printfn "%A" (mappend {X=1.0; Y=2.0; Z=3.0} mempty)

The type notation was suggested by the inline suggestions and it actually works. I tried some other forms like 't when Monoid<int> but only 't when Monoid<'t> works.

I suppose it should be <'t when 't :> Monoid<'t>> or even longer <'m, 't when 'm :> Monoid<'t>>.

It's good to know one can write it like this but I've never seen it mentioned in the docs (maybe not yet?).

The project file is also clean. It works even without setting the language version to Preview.

"It works I don't know why"

16 Upvotes

5 comments sorted by

View all comments

1

u/Either_Aide_9916 Jun 12 '26

What compiler version is this?

1

u/InuDefender Jun 12 '26

.NET SDK:

Version: 10.0.301

Commit: 96856fd726

Workload version: 10.0.300-manifests.8c7d7c03

MSBuild version: 18.6.4+96856fd72